Compare commits

...

158 Commits

Author SHA1 Message Date
aswin ebfcbb85fe Merge pull request 'feat/pdf-generator' (#51) from feat/pdf-generator into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #51
2024-08-03 19:52:58 +00:00
Aswin Ashar Abdullah feee9a3439 fix(SPG-494) PDF Generator 2024-08-04 02:51:11 +07:00
aswin b05e6fab5a Merge pull request 'development' (#50) from development into feat/pdf-generator
Reviewed-on: #50
2024-08-02 12:01:09 +00:00
aswin 37350e454f Merge pull request 'fix/data' (#49) from fix/data into development
Reviewed-on: #49
2024-08-02 12:00:23 +00:00
Aswin Ashar Abdullah b08325a53c fix(email) checkpoint email service 2024-08-02 18:59:31 +07:00
Aswin Ashar Abdullah a1f7108bc5 feat(SPG-233) Integration Google Calendar API 2024-08-02 18:36:42 +07:00
Aswin Ashar Abdullah 2e4d5df17a fix(SPG-762) BE - integrasi dengan API Midtrans - untuk update status pembayaran 2024-08-02 18:11:36 +07:00
Aswin Ashar Abdullah 4fcd852d8d fix(SPG-769) save edit data terkena validasi status transaksi settled 2024-08-02 17:59:30 +07:00
Aswin Ashar Abdullah 0f05656ca2 fix(booking) perbaikan column payment type counter 2024-08-02 17:54:12 +07:00
Aswin Ashar Abdullah 0bec3c6590 fix(SPG-750) Ketika sales di PoS di cancel, pada rekondiliasi - recap, valuenya tidak berkurang 2024-08-02 17:53:29 +07:00
Aswin Ashar Abdullah 8eee99fce5 fix(SPG-745) Data booking status active dan settled (tipe pembayaran selain counter) belum masuk PoS 2024-08-02 17:49:11 +07:00
Aswin Ashar Abdullah 239e2d778a feat(SPG-760) Validasi Bundling dan Item active inactive 2024-08-02 17:12:12 +07:00
Aswin Ashar Abdullah cc01b23e2a fix(SPG-754) Di hak akses PoS, penjualan seharusnya tidak ada check box delete 2024-08-02 16:56:34 +07:00
Aswin Ashar Abdullah 0b502188af fix(SPG-687) Booking status pending seharusnya bisa di cancel 2024-08-02 16:08:26 +07:00
Aswin Ashar Abdullah e38fbc65bd fix(SPG-759) Ketika ada item baru dibuat ( kondisi sudah ada data item rate untuk product lain ) 2024-08-02 16:00:05 +07:00
Aswin Ashar Abdullah 0e47b99ca7 fix(SPG-756) Untuk value field sales margin (%) seharusnya bisa mempunyai value dibelakang koma 2024-08-02 15:28:56 +07:00
Aswin Ashar Abdullah e401a1bf4c fix(SPG-742) Filter status, sumber, tipe pembayaran, pembayaran via, bank, tgl konfirmasi belum jalan 2024-08-02 15:16:43 +07:00
Aswin Ashar Abdullah 1636f6b930 fix(SPG-743) Refund dengan code invoice yang sama terkena validasi 2024-08-02 14:38:36 +07:00
aswin d1892e7aa5 Merge pull request 'development' (#48) from development into feat/pdf-generator
Reviewed-on: #48
2024-08-02 06:32:20 +00:00
Firman Ramdhani d14d9101ae feat: add report CashierLogReport and CashWithdrawalsReport
continuous-integration/drone/tag Build is passing Details
2024-08-01 18:09:40 +07:00
Firman Ramdhani 746e24feb6 feat: add migration for table pos log
continuous-integration/drone/tag Build is passing Details
2024-08-01 17:48:21 +07:00
Firman Ramdhani 39d7eb28b9 Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into development 2024-08-01 17:45:55 +07:00
Firman Ramdhani 9d0d76120e feat: update model pos log 2024-08-01 17:45:33 +07:00
aswin 971407612c Merge pull request 'fix/data' (#47) from fix/data into development
Reviewed-on: #47
2024-08-01 10:37:35 +00:00
Aswin Ashar Abdullah 03ec533e86 fix(SPG-736) Cancel rekon statu Pending terkena validasi data pemesanan harus settled 2024-08-01 17:33:36 +07:00
Aswin Ashar Abdullah d413bd771b fix(SPG-735) Ketika recap di click berkali kali, transaksi menggunakan tipe cash jadi duplicate 2024-08-01 17:25:12 +07:00
Aswin Ashar Abdullah 11171b2859 fix(SPG-729) pemesanan data seharusnya berstatus proses refund ketika data refund berstatus draft 2024-08-01 17:01:39 +07:00
Firman Ramdhani 1e9cc9da4f feat: add default condition for type on booking report 2024-08-01 15:13:00 +07:00
Firman Ramdhani 46307774e1 Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into development 2024-08-01 14:43:43 +07:00
Firman Ramdhani 62eccf29a5 feat: rename header title report 2024-08-01 14:43:37 +07:00
Aswin Ashar Abdullah 383fdce9f7 feat(pdf) checkpoint pdf 2024-08-01 14:36:20 +07:00
Aswin Ashar Abdullah 1ae7f4e097 fix(booking) perbaikan event deleted booking 2024-08-01 14:27:57 +07:00
aswin 33f955c209 Merge pull request 'fix/data' (#46) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #46
2024-08-01 07:01:41 +00:00
Aswin Ashar Abdullah d4bd3d746c fix(filter) perbaikan filter season period 2024-08-01 14:00:14 +07:00
Aswin Ashar Abdullah 45f11003f2 fix(privilege) perbaikan privilege constants 2024-08-01 13:33:02 +07:00
Aswin Ashar Abdullah 2188d63943 fix(SPG-726) Update image pada item status active, data image tidak ter sync ke PoS 2024-07-31 19:05:08 +07:00
Aswin Ashar Abdullah 3af56fa5d5 fix(SPG-652) Item Tipe Bundling - validasi 2024-07-31 18:51:31 +07:00
aswin 77d8e7ae1e Merge pull request 'fix/data' (#45) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #45
2024-07-31 11:27:39 +00:00
Aswin Ashar Abdullah c49bb379bd fix(item price) perbaikan price item 2024-07-31 18:25:28 +07:00
Aswin Ashar Abdullah 0648eeffee fix(SPG-711) Internal server error sering sekali ketika confirm status draft ke status pending 2024-07-31 18:24:47 +07:00
Aswin Ashar Abdullah e8deba2882 fix(SPG-709) Data summary transaksi PoS tidak muncul di halaman rekonsiliasi setelah click button recap 2024-07-31 17:58:33 +07:00
Aswin Ashar Abdullah 19386c336e fix(SPG-710) ganti warning cancel jadi bahasa indonesia 2024-07-31 17:58:01 +07:00
Aswin Ashar Abdullah 58cf3f7ab0 fix(SPG-718) Validasi perubahan tipe wahana seharusnya tidak memvalidasi perubahan namanya 2024-07-31 16:29:04 +07:00
Aswin Ashar Abdullah d7c4b27749 feat(SPG-719) Season Period - API Index - tambahkan filter berdasarkan season type 2024-07-31 16:19:30 +07:00
Aswin Ashar Abdullah 0ac5754170 fix(SPG-703) Sync account superadmin ke Pouch Couch supaya bisa login di PoS 2024-07-31 16:11:59 +07:00
Aswin Ashar Abdullah b7557a5f19 fix(SPG-663) Pos Privileges - pemesanan seharusnya tidak ada create 2024-07-31 15:53:41 +07:00
aswin 1590080468 Merge pull request 'fix(transaction) perbaikan data' (#44) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #44
2024-07-30 12:26:06 +00:00
Aswin Ashar Abdullah 61c512f7f4 fix(transaction) perbaikan data 2024-07-30 19:25:22 +07:00
aswin 30ffdca550 Merge pull request 'fix/data' (#43) from fix/data into development
continuous-integration/drone/tag Build is failing Details
Reviewed-on: #43
2024-07-30 11:33:11 +00:00
Aswin Ashar Abdullah c154af6cb7 fix(SPG-708) Muncul error saat meng cancel status pending - warninnya hanya bisa meng cancel status pending juga 2024-07-30 18:26:50 +07:00
Aswin Ashar Abdullah 197b3478ae fix(SPG_693) di hak akses pos pada bagian penjualan seharusnya ada checkbox pada kolom cancel dan ada hak akses reprint receipt 2024-07-30 18:22:23 +07:00
Aswin Ashar Abdullah c6be42299e fix(SPG-697) Pada index booking seharusnya transaksi pos tidak muncul, dan sesuaikan alur booking dengan pembayaran counter 2024-07-30 17:12:55 +07:00
Firman Ramdhani 9bcc72a69e feat: fix set false bookmark report
continuous-integration/drone/tag Build is passing Details
2024-07-30 16:59:11 +07:00
Aswin Ashar Abdullah dc6476a66f fix(SPG-687) Booking status pending seharusnya bisa di cancel, tapi ketika di cancel muncul error message, hanya status active yang bisa di cancel 2024-07-30 14:44:12 +07:00
Aswin Ashar Abdullah 4a9ca5eb5b fix(SPG-688) Ketika tgl booking di rubah web admin, tanggal booking pada PoS tidak ikut terupdate 2024-07-30 14:36:49 +07:00
aswin e1004b3843 Merge pull request 'fix/data' (#42) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #42
2024-07-30 06:56:07 +00:00
Aswin Ashar Abdullah 6632222c4b fix(SPG-677) Pada Index tgl invoice belum ada datanya, invoice data = tgl ketika booking di confirm ke status pending 2024-07-30 13:54:00 +07:00
Aswin Ashar Abdullah 945edbf76d fix(SPG-659) Muncul error get data saat confirm transaksi status draft ke pending 2024-07-30 13:50:23 +07:00
Aswin Ashar Abdullah 190f42d598 fix(SPG-645) Button generate price belum berfungsi 2024-07-30 13:46:57 +07:00
Aswin Ashar Abdullah d9bbe1290d fix(SPG-675) Error saat confirm status pending ( hanya bisa refund status settled ) padahal status sudah berubah ke proces refund 2024-07-30 13:08:50 +07:00
Aswin Ashar Abdullah 3e85d40885 feat(SPG-651) BE Reason Refund Request 2024-07-30 13:00:49 +07:00
Aswin Ashar Abdullah 7e38a67e80 fix(SPG-667) Kategori item status inactive seharusnya tidak terpanggil 2024-07-30 12:44:57 +07:00
Aswin Ashar Abdullah b91d9f7da8 fix(SPG-671) Item Bundling - validasi / warning jika item dalam bundling diinactivekan sedangkan masih berelasi, bundling harus di inactivekan dulu atau didelete 2024-07-30 12:24:31 +07:00
irfan bf8987242b Merge pull request 'fix: change query runner to repository from base manager' (#41) from fix/base-query into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #41
2024-07-29 09:47:00 +00:00
shancheas 57f2700c94 fix: change query runner to repository from base manager 2024-07-29 16:44:23 +07:00
Aswin Ashar Abdullah b3f0752ca0 fix(SPG-662) Search title banner belum jalan 2024-07-29 14:53:22 +07:00
Aswin Ashar Abdullah 33438f37ec fix(SPG-669) Validasi perubahan tipe wahana jika sudah mempunyai item yang berelasi 2024-07-29 14:48:05 +07:00
Aswin Ashar Abdullah 593955574a fix(SPG-664) admin Privilles - rekonsiliasi seharusnya tidak ada create 2024-07-29 14:37:46 +07:00
Aswin Ashar Abdullah 4ac711add5 fix(SPG-663) Pos Privilleges - pemesanan seharusnya tidak ada create 2024-07-29 14:37:12 +07:00
aswin c7fa402663 Merge pull request 'fix/data' (#40) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #40
2024-07-26 10:20:47 +00:00
Aswin Ashar Abdullah 6096771597 fix(SPG-658) Validasi - tidak bisa confirm dari status pending ke waiting, ketika data pembayaran booking belum diisi ( untuk pembayaran bank transfer dan QRIS saja) 2024-07-26 17:14:04 +07:00
Aswin Ashar Abdullah 76fa380f1e fix(SPG-657) Kode Pembayaran - ketika booking status waiting di confirm di rekonsiliasi, kode pembayaran tidak muncul 2024-07-26 16:49:52 +07:00
Aswin Ashar Abdullah 1f4bf80908 fix(SPG-661) Filter rekonsiliasi exclude status draft 2024-07-26 16:28:25 +07:00
Aswin Ashar Abdullah 66c481c9b0 fix(SPG-645) Button generate price belum berfungsi 2024-07-26 16:20:22 +07:00
Aswin Ashar Abdullah 9cd50ad817 fix(SPG-655) Item Rate saat filter harga jadi mengambil base price (kemungkinan ada salah ambil priority 2024-07-26 15:43:34 +07:00
Aswin Ashar Abdullah 82105e8214 fix(rate) perbaikan update rate 2024-07-26 15:05:28 +07:00
Aswin Ashar Abdullah e68524380a fix(SPG-652) Item Tipe Bundling - Item yang sudah berrelasi atau dipakai pada bundling tidak dapat di delete atau di inactivekan sampai di lepas dari bundling nya 2024-07-26 15:03:37 +07:00
aswin d333ba03a7 Merge pull request 'fix(season) update fix priority' (#39) from fix/data into development
Reviewed-on: #39
2024-07-26 07:04:31 +00:00
Aswin Ashar Abdullah a63eaf0110 fix(season) update fix priority 2024-07-26 14:03:38 +07:00
Aswin Ashar Abdullah e32a7c2eaf fix(base) delete query transaction
continuous-integration/drone/tag Build is passing Details
2024-07-26 11:41:18 +07:00
aswin 07f379a6b0 Merge pull request 'fix/data' (#38) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #38
2024-07-26 03:06:59 +00:00
Aswin Ashar Abdullah 39896fed90 fix(env) update env value 2024-07-26 10:06:11 +07:00
Aswin Ashar Abdullah a671404947 feat(SPG-554) BE - Integrasi Booking dengan Google Calendar 2024-07-25 16:03:43 +07:00
aswin 00d5eba7ab Merge pull request 'fix/data' (#37) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #37
2024-07-23 12:58:11 +00:00
Aswin Ashar Abdullah d0163ae003 feat(SPG-125) Logging 2024-07-23 19:54:00 +07:00
Aswin Ashar Abdullah aa550f9d38 feat(SPG-612) Activity Log PoS 2024-07-23 19:24:40 +07:00
Aswin Ashar Abdullah 2fc80c7cfc fix(SPG-640) Sync harga ketika ditambahkan melalui item rate (case item sudah dibuat) 2024-07-23 18:25:57 +07:00
Aswin Ashar Abdullah 20848aab3c fix(SPG-644) Sync ketika privileges di update 2024-07-23 18:25:14 +07:00
aswin d81eaac4f6 Merge pull request 'fix/data' (#36) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #36
2024-07-22 11:34:52 +00:00
Aswin Ashar Abdullah 679b98d198 fix(SPG-611) Upload - pemindahan directory upload image 2024-07-22 18:33:50 +07:00
Aswin Ashar Abdullah 1ff5461311 fix(SPG-645) Button generate price belum berfungsi 2024-07-22 12:29:36 +07:00
Firman Ramdhani 2f9c96bdec Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into development
continuous-integration/drone/tag Build is passing Details
2024-07-22 11:56:42 +07:00
Firman Ramdhani b1bc05fcb9 feat: adjustment report 2024-07-22 11:56:35 +07:00
Aswin Ashar Abdullah ef2697a3b1 fix(SPG-618) Error pada saat mengkonfirmasi / save pengembalian wahana baru 2024-07-22 11:40:43 +07:00
aswin 000c3f1800 Merge pull request 'fix/data' (#33) from fix/data into development
Reviewed-on: #33
2024-07-22 04:06:42 +00:00
Aswin Ashar Abdullah c5cec31ab5 fix(SPG-641) Validasi ketika process save untuk aksi di rekonsiliasi, save data di refund, dan aksi di booking 2024-07-20 22:12:09 +07:00
Aswin Ashar Abdullah cc92ef26a1 fix(index) perbaikan index item - item rates 2024-07-19 17:47:09 +07:00
Aswin Ashar Abdullah 1560cb0512 fix(SPG-643) Sync batch data couch pouch 2024-07-19 17:46:48 +07:00
Aswin Ashar Abdullah fba7b9aae5 fix(SPG-620) Sales Price & Profit Share Formula - Tambahkan warning/validasi jika formula menyebabkan error 2024-07-19 14:43:47 +07:00
Aswin Ashar Abdullah 0b236cb879 fix(SPG-619) Informasi Season Periode tidak muncul jika tgl dipilih bukan tanggal hari ini 2024-07-19 13:27:17 +07:00
aswin 41f4773df6 Merge pull request 'fix/data' (#32) from fix/data into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #32
2024-07-18 11:15:25 +00:00
Aswin Ashar Abdullah 908834cdd9 fix(item) perbaikan item price 2024-07-18 18:14:46 +07:00
Aswin Ashar Abdullah 4840abf18e fix(index) perbaikan index data sort by order 2024-07-18 15:36:56 +07:00
Aswin Ashar Abdullah cd6a5737e7 fix(SPG-600) Filter Sumber, Tipe, Kontak pada index booking belum berjalan 2024-07-18 15:36:38 +07:00
aswin 853543ece5 Merge pull request 'feat/midtrans' (#31) from feat/midtrans into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #31
2024-07-18 06:40:04 +00:00
Aswin Ashar Abdullah 37b12c960f fix(change-position) perbaikan change position module 2024-07-18 13:36:22 +07:00
Aswin Ashar Abdullah 8c9d0d6585 feat(SPG-423) Midtrans Integration 2024-07-18 12:45:46 +07:00
Aswin Ashar Abdullah 2551521539 feat(SPG-423) Midtrans Integration 2024-07-18 12:42:47 +07:00
Aswin Ashar Abdullah 403a75c835 feat(SPG-388) BE Send Mail with Google Mail 2024-07-17 19:10:35 +07:00
Firman Ramdhani 12359f3685 feat: setup colum report pengembalian
continuous-integration/drone/tag Build is passing Details
2024-07-17 14:18:59 +07:00
Firman Ramdhani d20fd4e175 feat: setup colum report pemesanan 2024-07-17 14:05:23 +07:00
aswin 05c98dcb14 Merge pull request 'feat/news' (#30) from feat/news into development
Reviewed-on: #30
2024-07-16 10:43:44 +00:00
firmanr d5bafe4f4f Merge pull request 'feat: fix get menu' (#29) from feat/privilege into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #29
2024-07-16 08:15:57 +00:00
Firman Ramdhani 6ca3766457 feat: fix get menu 2024-07-16 15:15:20 +07:00
Aswin Ashar Abdullah 9ac1fa9ae2 feat(SPG-460) REST API Read Banner 2024-07-16 13:30:33 +07:00
Aswin Ashar Abdullah 4178b72af9 feat(SPG-457) REST API CUD Banner 2024-07-16 13:30:17 +07:00
Aswin Ashar Abdullah bfa8d6d524 fix(filter) perbaikan filter search 2024-07-16 13:17:58 +07:00
Aswin Ashar Abdullah 7a74711834 feat(SPG-451) REST API Read berita 2024-07-16 13:17:41 +07:00
Aswin Ashar Abdullah 9056b60937 feat(SPG-448) REST API CUD Berita 2024-07-16 13:17:06 +07:00
Aswin Ashar Abdullah 75663c4f99 feat(SPG-521) Base Upload
continuous-integration/drone/tag Build is passing Details
2024-07-15 18:09:01 +07:00
Aswin Ashar Abdullah c2b5f27b3b fix(refund) perbaikan refund item 2024-07-15 18:08:44 +07:00
firmanr 84f7ed6d09 Merge pull request 'feat/privilege' (#28) from feat/privilege into development
continuous-integration/drone/tag Build was killed Details
Reviewed-on: #28
2024-07-15 11:07:31 +00:00
Firman Ramdhani eaa1e64899 feat: set exclude privilege on report api 2024-07-15 18:06:25 +07:00
Firman Ramdhani bad83aef69 Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into feat/privilege 2024-07-15 17:05:11 +07:00
Firman Ramdhani fc36997b91 feat: create api get privilege menu 2024-07-15 16:57:16 +07:00
Aswin Ashar Abdullah 7e18580540 fix(SPG-607) Transaksi booking dengan pembayaran tipe counter, tidak ada status waiting, dan tidak masuk ke rekonsiliasi
continuous-integration/drone/tag Build is passing Details
2024-07-15 16:49:54 +07:00
Aswin Ashar Abdullah e64799f7de fix(SPG-610) Membuat data season periode hari libur saja, ketika di save terbuat data season periode all juga 2024-07-15 16:40:45 +07:00
Aswin Ashar Abdullah 78ae2a5d8e fix(SPG-602) Harga Item belum mengambil harga season periode 2024-07-15 16:21:15 +07:00
Aswin Ashar Abdullah b574d3a39d fix(refund) perbaikan data refund
continuous-integration/drone/tag Build is passing Details
2024-07-15 15:24:02 +07:00
Aswin Ashar Abdullah eafd815463 feat(SPG-443) REST API Read FAQ 2024-07-15 15:17:36 +07:00
Aswin Ashar Abdullah 5a96282bce feat(SPG-440) REST API CUD FAQ 2024-07-15 15:17:01 +07:00
Aswin Ashar Abdullah 55d25644dd feat(SPG-437) REST API Read TnC 2024-07-15 15:12:47 +07:00
Aswin Ashar Abdullah 7a3d4b9432 feat(SPG-433) REST API CUD TnC 2024-07-15 15:02:17 +07:00
Aswin Ashar Abdullah af1a642907 feat(SPG-428) REST API Read Data Gate 2024-07-15 14:28:45 +07:00
Aswin Ashar Abdullah 0d2e49f93a feat(SPG-425) REST API CUD Data Gate 2024-07-15 14:28:25 +07:00
Aswin Ashar Abdullah 688be5828d fix(SPG-601) Confirm data status draft error - Cannot read properties of null (reading 'count')
continuous-integration/drone/tag Build is passing Details
2024-07-15 12:43:57 +07:00
Aswin Ashar Abdullah 001f371244 fix(SPG-600) Filter Sumber, Tipe, Kontak pada index booking belum berjalan 2024-07-15 12:43:17 +07:00
aswin 2a8d5e87cf Merge pull request 'feat/refund' (#27) from feat/refund into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #27
2024-07-12 10:52:01 +00:00
Aswin Ashar Abdullah 5c0886316c fix(format) perbaikan format and clean console log 2024-07-12 17:50:21 +07:00
Aswin Ashar Abdullah daf325b1a0 feat(SPG-393) REST API Read Refund 2024-07-12 17:49:57 +07:00
Aswin Ashar Abdullah 2ed4ce0199 feat(SPG-389) REST API CUD Refund 2024-07-12 17:30:15 +07:00
Aswin Ashar Abdullah 66fd9c16b2 fix(SPG-595) Pemesanan - Penyesuaian flow booking
continuous-integration/drone/tag Build is passing Details
2024-07-11 21:51:08 +07:00
Aswin Ashar Abdullah 9242f43760 fix(SPG-595) Pemesanan - Penyesuaian flow booking 2024-07-11 18:14:05 +07:00
Aswin Ashar Abdullah de2041ae95 fix(SPG-595) Pemesanan - Penyesuaian flow booking 2024-07-11 17:30:47 +07:00
aswin eb32584205 Merge pull request 'fix(SPG-595) Pemesanan - Penyesuaian flow booking' (#26) from fix/transaction into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #26
2024-07-10 10:38:52 +00:00
Aswin Ashar Abdullah f4969a837c fix(SPG-595) Pemesanan - Penyesuaian flow booking 2024-07-10 17:37:43 +07:00
Firman Ramdhani 59cf933abc feat: fix export group
continuous-integration/drone/tag Build is passing Details
2024-07-09 19:28:11 +07:00
Firman Ramdhani 2f03f18d51 Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into development
continuous-integration/drone/tag Build is passing Details
2024-07-09 18:44:12 +07:00
Firman Ramdhani 12543ea00b feat: adjustment api get config report 2024-07-09 18:44:05 +07:00
irfan c9b55c3d91 Merge pull request 'fix/type-data' (#25) from fix/type-data into development
Reviewed-on: #25
2024-07-09 11:25:20 +00:00
shancheas 0d7951d5f0 ci: update env COUCHDB_CONFIG 2024-07-09 18:13:38 +07:00
shancheas 34909a30b0 Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into fix/type-data 2024-07-09 17:53:37 +07:00
Aswin Ashar Abdullah 99847ce85b fix(SPG-593) Pemesanan - Update Pembayaran Pending - Tambahkan informasi pembayaran via dan no rekening 2024-07-09 17:52:46 +07:00
Aswin Ashar Abdullah 28dcac39f0 feat(SPG-405) DB Kode Diskon VIP 2024-07-09 17:52:04 +07:00
shancheas 6261592339 lint: update type data and lint 2024-07-09 17:47:15 +07:00
shancheas c87c852509 fix: update nano db configuration 2024-07-09 17:37:22 +07:00
shancheas 99261f37cd fix: change String type data to string 2024-07-09 17:20:10 +07:00
firmanr 56e7d25acd Merge pull request 'feat: fix filter boolean' (#24) from feat/report into development
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #24
2024-07-08 23:09:43 +00:00
477 changed files with 16520 additions and 1145 deletions

25
env/env.development vendored
View File

@ -6,6 +6,8 @@ JWT_REFRESH_EXPIRES="7d"
ENC_KEY="921c83f3b90c92dca4ba9b947f99b4c9" ENC_KEY="921c83f3b90c92dca4ba9b947f99b4c9"
IV="a671a96159e97a4f" IV="a671a96159e97a4f"
COUCHDB_CONFIG="http://root:password@172.10.10.2:5970"
DEFAULT_DB_HOST="postgres" DEFAULT_DB_HOST="postgres"
DEFAULT_DB_PORT="5432" DEFAULT_DB_PORT="5432"
DEFAULT_DB_USER="root" DEFAULT_DB_USER="root"
@ -16,4 +18,25 @@ ELASTIC_APM_ACTIVATE=true
ELASTIC_APM_SERVICE_NAME="Skyworld POS" ELASTIC_APM_SERVICE_NAME="Skyworld POS"
ELASTIC_APM_SERVER_URL="http://172.10.10.10:8200" ELASTIC_APM_SERVER_URL="http://172.10.10.10:8200"
EXPORT_LIMIT_PARTITION=200 CRON_MIDNIGHT="55 11 * * *"
CRON_EVERY_MINUTE="55 11 * * *"
CRON_EVERY_HOUR="0 * * * *"
EMAIL_HOST=smtp.gmail.com
EMAIL_POST=465
EMAIL_USER=weplayground.app@gmail.com
EMAIL_TOKEN=sonvvwiukhsevtmv
// nama email yang akan muncul ke user sebagai pengirim
EMAIL_SENDER=no-reply@eigen.co.id
MIDTRANS_URL=https://app.sandbox.midtrans.com
MIDTRANS_PRODUCTION=false
MIDTRANS_SERVER_KEY=SB-Mid-server-kH9_RBZrTwaUkxSrC5vOVaeG
MIDTRANS_CLIENT_KEY=SB-Mid-client-7XLwqG5cgjUmZj-7
EXPORT_LIMIT_PARTITION=200
ASSETS="https://asset.sky.eigen.co.id/"
GOOGLE_CALENDAR_KEY="AIzaSyCSg4P3uC9Z7kD1P4f3rf1BbBaz4Q-M55o"
GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec10bd5@group.calendar.google.com"

39
env/env.production vendored Normal file
View File

@ -0,0 +1,39 @@
PORT="3346"
JWT_SECRET="ftyYM4t4kjuj/0ixvIrS18gpdvBJw42NnW71GrFrEhcn0alQkkH7TQIHU5MFFJ1e"
JWT_EXPIRES="24h"
JWT_REFRESH_EXPIRES="7d"
ENC_KEY="921c83f3b90c92dca4ba9b947f99b4c9"
IV="a671a96159e97a4f"
COUCHDB_CONFIG="http://root:password@172.10.10.2:5970"
DEFAULT_DB_HOST="postgres"
DEFAULT_DB_PORT="5432"
DEFAULT_DB_USER="root"
DEFAULT_DB_PASS="password"
DEFAULT_DB_NAME="pos"
ELASTIC_APM_ACTIVATE=true
ELASTIC_APM_SERVICE_NAME="Skyworld POS"
ELASTIC_APM_SERVER_URL="http://172.10.10.10:8200"
CRON_MIDNIGHT="55 11 * * *"
CRON_EVERY_MINUTE="55 11 * * *"
CRON_EVERY_HOUR="0 * * * *"
EMAIL_HOST=smtp.gmail.com
EMAIL_POST=465
EMAIL_USER=weplayground.app@gmail.com
EMAIL_TOKEN=sonvvwiukhsevtmv
MIDTRANS_URL=https://app.midtrans.com
MIDTRANS_PRODUCTION=true
MIDTRANS_SERVER_KEY=Mid-server-BZlPCcrWHDuSxW48oxBs5uAl
MIDTRANS_CLIENT_KEY=Mid-client-YhOPuo0NZPNZfiKq
EXPORT_LIMIT_PARTITION=200
ASSETS="https://asset.sky.eigen.co.id/"
GOOGLE_CALENDAR_KEY="AIzaSyCSg4P3uC9Z7kD1P4f3rf1BbBaz4Q-M55o"
GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec10bd5@group.calendar.google.com"

BIN
fonts/Roboto-Black.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/Roboto-Bold.ttf Normal file

Binary file not shown.

BIN
fonts/Roboto-BoldItalic.ttf Normal file

Binary file not shown.

BIN
fonts/Roboto-Italic.ttf Normal file

Binary file not shown.

BIN
fonts/Roboto-Light.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/Roboto-Medium.ttf Normal file

Binary file not shown.

Binary file not shown.

BIN
fonts/Roboto-Regular.ttf Normal file

Binary file not shown.

BIN
fonts/Roboto-Thin.ttf Normal file

Binary file not shown.

BIN
fonts/Roboto-ThinItalic.ttf Normal file

Binary file not shown.

13
google-credential.json Normal file
View File

@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "weplayground-app",
"private_key_id": "e3ed1a4430140ac589c6e9e7ce125d16d8f7304a",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCmEl90K7ojdx1\nnJv5BKq3THI+l+pgC4dlqOuEV4sc2SFXECgyEgEYAFH6U8eH9TTl5wW5hFhvpiWl\nHSxZA2nMa1ojp97mkufzaGgsJbcB4ni9ydoJyN9Hqs2Wz+JiBtjscGOrmOP1bNyn\nBO9RhHInh0bfTNMrtsIicr4DPNIfM2sl95v6pCDGt7Cfu2NoEnDhId50d73KVONI\n0+rf90WhehEMwoZEzYI0gLmSVbnPEm1j4/OOQfQl7FjaFKyle+A5BWaiRsIqiSue\n0jvZz0DlGmjeHx1yjBIKpq5omOku7aYi4kTNEZKKxzs5HhRFKi2KuYNK/WD5ApQg\ncIhGhhCfAgMBAAECggEANX+LmNjh9VJm/Tigkt4LFxifwgCe8WfKAhNmKHyu5K/3\nIAnzmwxjG5ee8gzNat3pfJk+dCnj7FIHwHScSB6NnCMZZXsV51sVBNC77wMxZIXA\nPyE63fzJEdlt6xvc96k9QweFB1yhs0wJ/6r2JnmcrqxcujBTUA3PIoxcG+TBOc08\ndo5Rcbeq6/3txjGlFM1820WViuFSQQiL6PgNVb+l0JrQ8rAOflKYFOkUb8wux9LX\nnD4vJMwa0j+GRvH5BCcZCguIQZn2JR3rTgcavWtcaHiTNsc49Lsj/hGGOsbkFROo\nGWaSgXE169xiVR/MMEblzqpSXq1qXF2iUeaqyUFIZQKBgQDxxrNlDs1qMfcaQ0S2\nVVtU/f1NfY+kCjQaC4CoYJaaoZINs5ODPs8/2DGnHuhNXMtnPeQ+SzNaK1e1eLbw\nmvq1+n3aGZTvUq2L3b+v7JJ6TQmQ4eBLZBzNjxrxC3EkCULTuROtsAhfzORuE0mE\nwnhR5LpPraEBrPi0re9yDDXVHQKBgQDOCwGw1gNVLh622qR65Zhx5rs2q6ktPxq2\neiUV0KDug6/7QbJzg1pNeoVQmadJR86H0fzKMsN5C7t7z3MIkqXc0+T1NmdN2fPm\ndLthnR1grCDYykoet/CITbAfiip27/o3TJ7YIYItefyZ4GnNH82R/4z3LBDnXB9f\n565hbUj76wKBgEnNMpOFijSBXgFZSU8zDPcLtNeDnWYgazkMC9DZ8v7ulOuzxjKI\n6LB/aOCvsY9z5O712IcfY2SB2HsfhxA47pDADsyVhH3tSeZo4QttdmT4wRPFrza0\nL4qbxUiRCo9KeGiylQwusM+1doEXSBjLV/j/jdOml4AwcZaNhYrVqVUNAoGAU0uD\nzXdXNZJFfGp7X+t9a155hKp05APEyswqPd1vkbzO4eY3PBd35CaJyoGzbR6IUcQE\nS8Gl4ENr8at1t5uBTfqjbrYloQVhYmMCdX3MqI4tYTa2LCD0LkYp0zZJ4Hc3Ui+5\nb2psc/ICujpMy032DvWeiTXZR46oaF8C0gQaIy0CgYEAmKCP4CXmPlWoWqebFp3W\nz2eKWUfASioQ+ZGUVNEge4a6iutciydQJZxBfg9ZXWqDfI0FoRSPfs2zUZFO0AcM\n6oaPGiFnTnH8FGcSHu3p0YysevyoSY6tgsAhb3IiKjJd4e7btsYzpPZbIfyfUVHK\nQFOOSkE+x4J5ts+XO6isQ+w=\n-----END PRIVATE KEY-----\n",
"client_email": "weplayground@weplayground-app.iam.gserviceaccount.com",
"client_id": "106351339097550564510",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/weplayground%40weplayground-app.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

BIN
image/logo.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View File

@ -37,15 +37,23 @@
"@nestjs/schedule": "^4.1.0", "@nestjs/schedule": "^4.1.0",
"@nestjs/swagger": "^7.3.1", "@nestjs/swagger": "^7.3.1",
"@nestjs/typeorm": "^10.0.2", "@nestjs/typeorm": "^10.0.2",
"@types/multer": "^1.4.11",
"algebra.js": "^0.2.6",
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"elastic-apm-node": "^4.5.4", "elastic-apm-node": "^4.5.4",
"exceljs": "^4.4.0", "exceljs": "^4.4.0",
"fs-extra": "^11.2.0",
"googleapis": "^140.0.0", "googleapis": "^140.0.0",
"handlebars": "^4.7.8",
"mathjs": "^13.0.2",
"midtrans-client": "^1.3.1",
"moment": "^2.30.1", "moment": "^2.30.1",
"nano": "^10.1.3", "nano": "^10.1.3",
"nodemailer": "^6.9.14",
"pdfmake": "^0.2.10",
"pg": "^8.11.5", "pg": "^8.11.5",
"plop": "^4.0.1", "plop": "^4.0.1",
"reflect-metadata": "^0.2.0", "reflect-metadata": "^0.2.0",

View File

@ -29,7 +29,7 @@ module.exports = function (plop) {
name: 'location', name: 'location',
message: 'Location: ', message: 'Location: ',
choices: function () { choices: function () {
return ['item related', 'user related', 'season related', 'transaction']; return ['item related', 'user related', 'season related', 'transaction', 'web information'];
}, },
}, },
], ],

View File

@ -47,13 +47,30 @@ import { TransactionModel } from './modules/transaction/transaction/data/models/
import { TransactionItemModel } from './modules/transaction/transaction/data/models/transaction-item.model'; import { TransactionItemModel } from './modules/transaction/transaction/data/models/transaction-item.model';
import { TransactionTaxModel } from './modules/transaction/transaction/data/models/transaction-tax.model'; import { TransactionTaxModel } from './modules/transaction/transaction/data/models/transaction-tax.model';
import { ReconciliationModule } from './modules/transaction/reconciliation/reconciliation.module'; import { ReconciliationModule } from './modules/transaction/reconciliation/reconciliation.module';
import { ReportModule } from './modules/reports/report/report.module'; import { ReportModule } from './modules/reports/report/report.module';
import { ReportBookmarkModule } from './modules/reports/report-bookmark/report-bookmark.module'; import { ReportBookmarkModule } from './modules/reports/report-bookmark/report-bookmark.module';
import { ReportExportModule } from './modules/reports/report-export/report-export.module'; import { ReportExportModule } from './modules/reports/report-export/report-export.module';
import { ReportBookmarkModel } from './modules/reports/shared/models/report-bookmark.model'; import { ReportBookmarkModel } from './modules/reports/shared/models/report-bookmark.model';
import { ExportReportHistoryModel } from './modules/reports/shared/models/export-report-history.model'; import { ExportReportHistoryModel } from './modules/reports/shared/models/export-report-history.model';
import { CronModule } from './modules/configuration/cron/cron.module'; import { CronModule } from './modules/configuration/cron/cron.module';
import { MidtransModule } from './modules/configuration/midtrans/midtrans.module';
import { RefundModule } from './modules/transaction/refund/refund.module';
import { RefundModel } from './modules/transaction/refund/data/models/refund.model';
import { RefundItemModel } from './modules/transaction/refund/data/models/refund-item.model';
import { GateModule } from './modules/web-information/gate/gate.module';
import { GateModel } from './modules/web-information/gate/data/models/gate.model';
import { TermConditionModule } from './modules/web-information/term-condition/term-condition.module';
import { TermConditionModel } from './modules/web-information/term-condition/data/models/term-condition.model';
import { FaqModel } from './modules/web-information/faq/data/models/faq.model';
import { FaqModule } from './modules/web-information/faq/faq.module';
import { UploadModule } from './modules/configuration/upload/upload.module';
import { NewsModule } from './modules/web-information/news/news.module';
import { NewsModel } from './modules/web-information/news/data/models/news.model';
import { BannerModule } from './modules/web-information/banner/banner.module';
import { BannerModel } from './modules/web-information/banner/data/models/banner.model';
import { MailModule } from './modules/configuration/mail/mail.module';
import { PosLogModel } from './modules/configuration/log/data/models/pos-log.model';
import { ExportModule } from './modules/configuration/export/export.module';
@Module({ @Module({
imports: [ imports: [
@ -71,16 +88,24 @@ import { CronModule } from './modules/configuration/cron/cron.module';
database: process.env.DEFAULT_DB_NAME, database: process.env.DEFAULT_DB_NAME,
entities: [ entities: [
...UserPrivilegeModels, ...UserPrivilegeModels,
BannerModel,
ErrorLogModel, ErrorLogModel,
FaqModel,
GateModel,
ItemModel, ItemModel,
ItemCategoryModel, ItemCategoryModel,
ItemRateModel, ItemRateModel,
LogModel, LogModel,
NewsModel,
PaymentMethodModel, PaymentMethodModel,
PosLogModel,
RefundModel,
RefundItemModel,
SalesPriceFormulaModel, SalesPriceFormulaModel,
SeasonPeriodModel, SeasonPeriodModel,
SeasonTypeModel, SeasonTypeModel,
TaxModel, TaxModel,
TermConditionModel,
TransactionModel, TransactionModel,
TransactionItemModel, TransactionItemModel,
TransactionTaxModel, TransactionTaxModel,
@ -99,9 +124,13 @@ import { CronModule } from './modules/configuration/cron/cron.module';
CqrsModule, CqrsModule,
CouchModule, CouchModule,
CronModule, CronModule,
ExportModule,
GoogleCalendarModule, GoogleCalendarModule,
LogModule, LogModule,
MailModule,
MidtransModule,
SessionModule, SessionModule,
UploadModule,
// user // user
TenantModule, TenantModule,
@ -117,6 +146,7 @@ import { CronModule } from './modules/configuration/cron/cron.module';
PaymentMethodModule, PaymentMethodModule,
ProfitShareFormulaModule, ProfitShareFormulaModule,
ReconciliationModule, ReconciliationModule,
RefundModule,
SalesPriceFormulaModule, SalesPriceFormulaModule,
TaxModule, TaxModule,
TransactionModule, TransactionModule,
@ -127,6 +157,13 @@ import { CronModule } from './modules/configuration/cron/cron.module';
SeasonTypeModule, SeasonTypeModule,
SeasonPeriodModule, SeasonPeriodModule,
// web information
BannerModule,
FaqModule,
GateModule,
NewsModule,
TermConditionModule,
// report // report
ReportModule, ReportModule,
ReportBookmarkModule, ReportBookmarkModule,

View File

@ -25,7 +25,7 @@ export class RolesGuard extends JWTGuard {
if (isNotAllow) { if (isNotAllow) {
throw new ForbiddenException({ throw new ForbiddenException({
statusCode: 10003, statusCode: 10003,
message: `Forbidden Access, you don't have access to this module!`, message: `Akses Terlarang, anda tidak punya akses ke module ini!`,
error: 'ACCESS_FORBIDDEN', error: 'ACCESS_FORBIDDEN',
}); });
} }

View File

@ -52,7 +52,7 @@ export class PrivilegeService {
if (!moduleKey) { if (!moduleKey) {
throw new ForbiddenException({ throw new ForbiddenException({
statusCode: 10005, statusCode: 10005,
message: `Forbidden Access, access Module is Require!`, message: `Akses Terlarang, anda tidak punya akses ke module ini!`,
error: 'MODULE_KEY_NOT_FOUND', error: 'MODULE_KEY_NOT_FOUND',
}); });
} }
@ -61,7 +61,7 @@ export class PrivilegeService {
} }
async privilegeConfiguration(): Promise<UserPrivilegeConfigurationEntity> { async privilegeConfiguration(): Promise<UserPrivilegeConfigurationEntity> {
const { module, menu, sub_menu, section } = this.moduleKey(); const { module, menu } = this.moduleKey();
return await this.repository.findOne({ return await this.repository.findOne({
select: ['id', 'view', 'create', 'edit', 'delete', 'cancel', 'confirm'], select: ['id', 'view', 'create', 'edit', 'delete', 'cancel', 'confirm'],
where: { where: {

View File

@ -0,0 +1,28 @@
import * as fs from 'fs-extra';
import * as path from 'path';
export async function MoveFilePathHelper(data) {
const imagePath = data['qr_image'] ?? data['image_url'];
const sourcePath = path.join(__dirname, '../../../../uploads/', imagePath);
const movePath =
'data/' +
imagePath
.split('/')
.filter((item) => !['uploads', 'tmp'].includes(item))
.join('/');
const destinationPath = path.join(
__dirname,
'../../../../uploads/',
movePath,
);
try {
await fs.move(sourcePath, destinationPath);
Object.assign(data, {
image_url: movePath,
});
} catch (error) {
console.log(`Failed! Error move file data`);
}
}

View File

@ -0,0 +1,44 @@
import { extname } from 'path';
import { v4 as uuidv4 } from 'uuid';
import { HttpException, HttpStatus } from '@nestjs/common';
import * as fs from 'fs';
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
import { diskStorage } from 'multer';
const MB = 1024 * 1024;
const fileFilter = (req, file, callback) => {
if (file.mimetype.match(/\/(jpg|jpeg|png)$/)) {
callback(null, true);
} else {
callback(
new HttpException(
`Unsupported file type ${extname(file.originalname)}`,
HttpStatus.BAD_REQUEST,
),
false,
);
}
};
const editFileName = (req, file, callback) => {
const fileExtName = extname(file.originalname);
const randomName = uuidv4();
callback(null, `${randomName}${fileExtName}`);
};
const destinationPath = (req, file, cb) => {
let modulePath = req.body.module;
if (req.body.sub_module) modulePath = `${modulePath}/${req.body.sub_module}`;
fs.mkdirSync(`./uploads/tmp/${modulePath}`, { recursive: true });
cb(null, `./uploads/tmp/${modulePath}`);
};
export const StoreFileConfig: MulterOptions = {
storage: diskStorage({
destination: destinationPath,
filename: editFileName,
}),
fileFilter: fileFilter,
};

View File

@ -43,9 +43,9 @@ export class CheckDuplicateHelper {
if (data_exists > 0) { if (data_exists > 0) {
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Entity with ${columnCheck.column} : ${ message: `Gagal! Data dengan ${columnCheck.column} : ${
this.entity[columnCheck.column] this.entity[columnCheck.column]
} already exist`, } telah ada`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
} }

View File

@ -10,39 +10,14 @@ export function setQueryFilterDefault(
baseFilter: BaseFilterEntity, baseFilter: BaseFilterEntity,
tableName: TABLE_NAME, tableName: TABLE_NAME,
): SelectQueryBuilder<any> { ): SelectQueryBuilder<any> {
// filter berdasarkan statuses
if (!!baseFilter.statuses) {
queryBuilder.andWhere(
new Brackets((qb) => {
baseFilter.statuses.map((status) => {
// trim search
const statusData = status.includes("'")
? status.trim().replace(/'/g, "''").replace(/\s+/g, ' ')
: status.trim().replace(/\s+/g, ' ');
// jika searching status terdapat dalam enum, maka dia mencari specific data
// ? karena jika tidak, ketika dia search "active" maka "inactive" juga ikut
if (STATUS[statusData.toUpperCase()])
qb.orWhere(`${tableName}.status = :statusData`, {
statusData: statusData,
});
else
qb['orWhere'](
`${tableName}.status::text ILIKE '%${[statusData]}%'`,
);
});
}),
);
}
// filter berdasarkan id pembuat // filter berdasarkan id pembuat
if (!!baseFilter.created_ids) if (!!baseFilter.created_ids)
new WhereInQueryHelper( new WhereInQueryHelper(
queryBuilder, queryBuilder,
tableName, tableName,
'created_id', 'creator_id',
baseFilter.created_ids, baseFilter.created_ids,
'created_ids', 'creator_ids',
).getQuery(); ).getQuery();
// filter berdasarkan tanggal terakhir dibuat // filter berdasarkan tanggal terakhir dibuat

View File

@ -20,12 +20,16 @@ export class SpecificSearchFilter<Entity = any> {
new Brackets((qb) => { new Brackets((qb) => {
params.forEach((param) => { params.forEach((param) => {
const { cols, data, additional, leftJoin } = param; const { cols, data, additional, leftJoin } = param;
const columns = cols.split('.');
let arr = data;
const arr = data?.map((el) => if (!columns.includes('status::text')) {
el.includes("'") arr = data?.map((el) =>
? `'%${el.trim().replace(/'/g, "''").replace(/\s+/g, ' ')}%'` el.includes("'")
: `'%${el.trim().replace(/\s+/g, ' ')}%'`, ? `'%${el.trim().replace(/'/g, "''").replace(/\s+/g, ' ')}%'`
); : `'%${el.trim().replace(/\s+/g, ' ')}%'`,
);
}
const aliases = !cols.match(/\./g) const aliases = !cols.match(/\./g)
? this.table.concat(`.${cols}`) ? this.table.concat(`.${cols}`)

View File

@ -17,8 +17,17 @@ export abstract class BaseDataService<Entity> {
entityTarget: EntityTarget<Entity>, entityTarget: EntityTarget<Entity>,
entity: Entity, entity: Entity,
): Promise<Entity> { ): Promise<Entity> {
const newEntity = queryRunner.manager.create(entityTarget, entity); // const newEntity = this.repository.create(entityTarget, entity);
return await queryRunner.manager.save(newEntity); return await this.repository.save(entity);
}
async createMany(
queryRunner: QueryRunner,
entityTarget: EntityTarget<Entity>,
entity: Entity[],
): Promise<Entity[]> {
// const newEntity = this.repository.create(entityTarget, entity);
return await this.repository.save(entity);
} }
async createBatch( async createBatch(
@ -26,8 +35,8 @@ export abstract class BaseDataService<Entity> {
entityTarget: EntityTarget<Entity>, entityTarget: EntityTarget<Entity>,
entity: Entity[], entity: Entity[],
): Promise<Entity[]> { ): Promise<Entity[]> {
const newEntity = queryRunner.manager.create(entityTarget, entity); // const newEntity = this.repository.create(entityTarget, entity);
return await queryRunner.manager.save(newEntity); return await this.repository.save(entity);
} }
async update( async update(
@ -36,13 +45,13 @@ export abstract class BaseDataService<Entity> {
filterUpdate: any, filterUpdate: any,
entity: Entity, entity: Entity,
): Promise<Entity> { ): Promise<Entity> {
const newEntity = await queryRunner.manager.findOne(entityTarget, { const newEntity = await this.repository.findOne({
where: filterUpdate, where: filterUpdate,
}); });
if (!newEntity) throw new Error('Data not found!'); if (!newEntity) throw new Error('Data not found!');
Object.assign(newEntity, entity); Object.assign(newEntity, entity);
return await queryRunner.manager.save(newEntity); return await this.repository.save(newEntity);
} }
async deleteById( async deleteById(
@ -50,7 +59,15 @@ export abstract class BaseDataService<Entity> {
entityTarget: EntityTarget<Entity>, entityTarget: EntityTarget<Entity>,
id: string, id: string,
): Promise<void> { ): Promise<void> {
await queryRunner.manager.delete(entityTarget, { id }); await this.repository.delete(id);
}
async deleteByIds(
queryRunner: QueryRunner,
entityTarget: EntityTarget<Entity>,
ids: string[],
): Promise<void> {
await this.repository.delete(ids);
} }
async deleteByOptions( async deleteByOptions(
@ -58,11 +75,8 @@ export abstract class BaseDataService<Entity> {
entityTarget: EntityTarget<Entity>, entityTarget: EntityTarget<Entity>,
findManyOptions: FindManyOptions<Entity>, findManyOptions: FindManyOptions<Entity>,
): Promise<void> { ): Promise<void> {
const datas = await queryRunner.manager.find(entityTarget, findManyOptions); const datas = await this.repository.find(findManyOptions);
await queryRunner.manager.delete( await this.repository.delete(datas?.map((item) => item['id']));
entityTarget,
datas?.map((item) => item['id']),
);
} }
async getOneByOptions(findOneOptions): Promise<Entity> { async getOneByOptions(findOneOptions): Promise<Entity> {

View File

@ -13,9 +13,11 @@ export abstract class BaseReadService<Entity> {
queryBuilder: SelectQueryBuilder<Entity>, queryBuilder: SelectQueryBuilder<Entity>,
params: BaseFilterEntity, params: BaseFilterEntity,
): Promise<PaginationResponse<Entity>> { ): Promise<PaginationResponse<Entity>> {
const limit = params.limit ?? 10;
const page = params.page ?? 1;
const [data, total] = await queryBuilder const [data, total] = await queryBuilder
.take(+params.limit) .take(+limit)
.skip(+params.limit * +params.page - +params.limit) .skip(+limit * +page - +limit)
.getManyAndCount(); .getManyAndCount();
return { return {

View File

@ -1,3 +1,3 @@
export interface BaseCoreEntity { export interface BaseCoreEntity {
id: string; id?: string;
} }

View File

@ -22,6 +22,7 @@ export interface Param {
data: string[]; data: string[];
additional?: any[]; additional?: any[];
leftJoin?: any[]; leftJoin?: any[];
isStatus?: boolean;
} }
export interface RelationParam { export interface RelationParam {

View File

@ -82,11 +82,11 @@ export abstract class BaseManager {
this.baseLog.verbose('commitTransaction'); this.baseLog.verbose('commitTransaction');
await this.queryRunner.commitTransaction(); await this.queryRunner.commitTransaction();
await this.queryRunner.release();
} catch (e) { } catch (e) {
if (e.response) throw new Error(JSON.stringify(e.response)); if (e.response) throw new Error(JSON.stringify(e.response));
else throw new Error(e.message); else throw new Error(e.message);
} finally {
await this.queryRunner.release();
} }
} }

View File

@ -25,7 +25,7 @@ export abstract class BaseBatchDeleteManager<Entity> extends BaseManager {
async process(): Promise<void> { async process(): Promise<void> {
let totalFailed = 0; let totalFailed = 0;
let totalSuccess = 0; let totalSuccess = 0;
let messages = []; const messages = [];
for (const id of this.dataIds) { for (const id of this.dataIds) {
try { try {
@ -38,7 +38,7 @@ export abstract class BaseBatchDeleteManager<Entity> extends BaseManager {
if (!entity) { if (!entity) {
throw new NotFoundException({ throw new NotFoundException({
statusCode: HttpStatus.NOT_FOUND, statusCode: HttpStatus.NOT_FOUND,
message: `Failed! Entity with id ${id} not found`, message: `Gagal! data dengan id ${id} tidak ditemukan`,
error: 'Entity Not Found', error: 'Entity Not Found',
}); });
} }

View File

@ -8,6 +8,7 @@ import * as _ from 'lodash';
export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager { export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
protected dataIds: string[]; protected dataIds: string[];
protected relations: string[] = [];
protected result: BatchResult; protected result: BatchResult;
protected dataStatus: STATUS; protected dataStatus: STATUS;
protected oldData: Entity; protected oldData: Entity;
@ -29,7 +30,7 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
async process(): Promise<void> { async process(): Promise<void> {
let totalFailed = 0; let totalFailed = 0;
let totalSuccess = 0; let totalSuccess = 0;
let messages = []; const messages = [];
for (const id of this.dataIds) { for (const id of this.dataIds) {
try { try {
@ -37,24 +38,25 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
where: { where: {
id: id, id: id,
}, },
relations: this.relations,
}); });
if (!entity) { if (!entity) {
throw new NotFoundException({ throw new NotFoundException({
statusCode: HttpStatus.NOT_FOUND, statusCode: HttpStatus.NOT_FOUND,
message: `Failed! Entity with id ${id} not found`, message: `Gagal! data dengan id ${id} tidak ditemukan`,
error: 'Entity Not Found', error: 'Entity Not Found',
}); });
} }
this.oldData = _.cloneDeep(entity); this.oldData = _.cloneDeep(entity);
await this.validateData(entity);
Object.assign(entity, { Object.assign(entity, {
status: this.dataStatus, status: this.dataStatus,
editor_id: this.user.id, editor_id: this.user.id,
editor_name: this.user.name, editor_name: this.user.name,
updated_at: new Date().getTime(), updated_at: new Date().getTime(),
}); });
await this.validateData(entity);
await new ValidateRelationHelper( await new ValidateRelationHelper(
id, id,
this.dataService, this.dataService,
@ -105,7 +107,7 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
if (!this.eventTopics.length) return; if (!this.eventTopics.length) return;
for (const topic of this.eventTopics) { for (const topic of this.eventTopics) {
let data; let data;
if (!topic.relations) { if (topic.relations?.length) {
data = await this.dataService.getOneByOptions({ data = await this.dataService.getOneByOptions({
where: { where: {
id: dataNew.id, id: dataNew.id,

View File

@ -0,0 +1,152 @@
import { BaseManager } from '../base.manager';
import {
EventTopics,
columnUniques,
validateRelations,
} from 'src/core/strings/constants/interface.constants';
import { HttpStatus, UnprocessableEntityException } from '@nestjs/common';
import { SelectQueryBuilder } from 'typeorm';
export abstract class BaseChangePosition<Entity> extends BaseManager {
protected result: Entity;
protected duplicateColumn: string[];
protected startData: Entity;
protected endData: Entity;
protected columnSort: string;
protected firstDataId: number;
protected lastSort: number;
protected sortTo: number;
abstract get entityTarget(): any;
setData(entity: Entity, columnSort: string): void {
this.data = entity;
this.columnSort = columnSort;
}
async beforeProcess(): Promise<void> {
if (!this.data?.end || this.data.start == this.data?.end) {
throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: 'Gagal! tolong pindahkan ke posisi lain',
error: 'Unprocessable Entity',
});
}
this.startData = await this.dataService.getOneByOptions({
where: {
id: this.data.start,
},
});
if (!this.startData) {
throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Gagal! data dengan id : ${this.data.start} tidak ditemukan`,
error: 'Unprocessable Entity',
});
}
this.endData = await this.dataService.getOneByOptions({
where: {
id: this.data.end,
},
});
if (!this.endData) {
throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Gagal! data dengan id : ${this.data.end} tidak ditemukan`,
error: 'Unprocessable Entity',
});
}
if (this.endData[this.columnSort] > this.startData[this.columnSort]) {
// drag from up
this.firstDataId = this.startData[this.columnSort];
this.lastSort = this.endData[this.columnSort];
this.sortTo = this.lastSort;
} else if (
this.endData[this.columnSort] < this.startData[this.columnSort]
) {
// drag from bottom
this.firstDataId = this.endData[this.columnSort];
this.lastSort = this.startData[this.columnSort];
this.sortTo = this.firstDataId;
}
}
async prepareData(): Promise<void> {
Object.assign(this.data, {
creator_id: this.user.id,
creator_name: this.user.name,
created_at: new Date().getTime(),
updated_at: new Date().getTime(),
});
}
async validateProcess(): Promise<void> {
return;
}
async process(): Promise<void> {
let dataArrange: Entity[];
const queryBuilder = this.dataService
.getRepository()
.createQueryBuilder(this.tableName)
.where(`${this.tableName}.${this.columnSort} between :data1 and :data2`, {
data1: this.firstDataId,
data2: this.lastSort,
});
const datas = await queryBuilder
.orderBy(`${this.tableName}.${this.columnSort}`, 'ASC')
.getManyAndCount();
if (datas[0].length) {
let dataFirst = datas[0][0][this.columnSort];
const data = datas[0];
const length = datas[1];
if (this.endData[this.columnSort] > this.startData[this.columnSort]) {
// drag from above
const dataDragged = data[0];
const arraySlice = data.slice(1, length);
dataArrange = arraySlice.concat([dataDragged]);
} else if (
this.endData[this.columnSort] < this.startData[this.columnSort]
) {
// drag from bottom
const dataDragged = data[length - 1];
const arraySlice = data.slice(0, length - 1);
dataArrange = [dataDragged].concat(arraySlice);
}
for (let i = 0; i < length; i++) {
dataArrange[i][this.columnSort] = dataFirst;
dataFirst++;
}
await this.dataService.createMany(
this.queryRunner,
this.entityTarget,
dataArrange,
);
}
}
get validateRelations(): validateRelations[] {
return [];
}
get eventTopics(): EventTopics[] {
return [];
}
getResult(): string {
return `Success! Data ${this.startData['name']} successfully moved to ${this.sortTo}`;
}
}

View File

@ -6,6 +6,7 @@ import {
columnUniques, columnUniques,
validateRelations, validateRelations,
} from 'src/core/strings/constants/interface.constants'; } from 'src/core/strings/constants/interface.constants';
import { MoveFilePathHelper } from 'src/core/helpers/path/move-file-path.helper';
export abstract class BaseCreateManager<Entity> extends BaseManager { export abstract class BaseCreateManager<Entity> extends BaseManager {
protected result: Entity; protected result: Entity;
@ -43,6 +44,15 @@ export abstract class BaseCreateManager<Entity> extends BaseManager {
} }
async process(): Promise<void> { async process(): Promise<void> {
const keys = Object.keys(this.data);
if (
(keys.includes('qr_image') || keys.includes('image_url')) &&
(this.data['image_url']?.includes('tmp') ||
this.data['qr_image']?.includes('tmp'))
) {
await MoveFilePathHelper(this.data);
}
this.result = await this.dataService.create( this.result = await this.dataService.create(
this.queryRunner, this.queryRunner,
this.entityTarget, this.entityTarget,
@ -75,11 +85,21 @@ export abstract class BaseCreateManager<Entity> extends BaseManager {
if (!this.eventTopics.length) return; if (!this.eventTopics.length) return;
for (const topic of this.eventTopics) { for (const topic of this.eventTopics) {
let data;
if (!topic.data) {
data = await this.dataService.getOneByOptions({
where: {
id: this.result['id'],
},
relations: topic.relations,
});
}
this.eventBus.publishAll([ this.eventBus.publishAll([
new topic.topic({ new topic.topic({
id: this.result['id'], id: this.result['id'],
old: null, old: null,
data: topic.data, data: data ?? topic.data,
user: this.user, user: this.user,
description: '', description: '',
module: this.tableName, module: this.tableName,

View File

@ -1,11 +1,12 @@
import { validateRelations } from 'src/core/strings/constants/interface.constants'; import { validateRelations } from 'src/core/strings/constants/interface.constants';
import { BaseManager } from '../base.manager'; import { BaseManager } from '../base.manager';
import { OPERATION } from 'src/core/strings/constants/base.constants';
export abstract class BaseCustomManager<Entity> extends BaseManager { export abstract class BaseCustomManager<Entity> extends BaseManager {
protected result: any; protected result: any;
abstract get entityTarget(): any; abstract get entityTarget(): any;
setData(entity: Entity): void { setData(entity: any): void {
this.data = entity; this.data = entity;
} }
@ -23,4 +24,31 @@ export abstract class BaseCustomManager<Entity> extends BaseManager {
} }
abstract getResult(): any; abstract getResult(): any;
async publishEvents() {
if (!this.eventTopics.length) return;
for (const topic of this.eventTopics) {
let data;
if (!topic.data) {
data = await this.dataService.getOneByOptions({
where: {
id: this.result['id'],
},
relations: topic.relations,
});
}
this.eventBus.publishAll([
new topic.topic({
id: data?.['id'] ?? topic?.data?.['id'],
old: null,
data: data ?? topic.data,
user: this.user,
description: '',
module: this.tableName,
op: OPERATION.UPDATE,
}),
]);
}
}
} }

View File

@ -23,7 +23,7 @@ export abstract class BaseDeleteManager<Entity> extends BaseManager {
if (!this.data) if (!this.data)
throw new UnprocessableEntityException({ throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY, statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Data with id ${this.dataId} not found`, message: `Gagal! Data denga id ${this.dataId} tidak ditemukan`,
error: 'Unprocessable Entity', error: 'Unprocessable Entity',
}); });
@ -67,7 +67,7 @@ export abstract class BaseDeleteManager<Entity> extends BaseManager {
this.eventBus.publishAll([ this.eventBus.publishAll([
new topic.topic({ new topic.topic({
id: topic.data['id'], id: topic.data['id'],
old: null, old: this.data,
data: topic.data, data: topic.data,
user: this.user, user: this.user,
description: '', description: '',

View File

@ -8,6 +8,7 @@ import {
} from 'src/core/helpers/query/default-filter.helper'; } from 'src/core/helpers/query/default-filter.helper';
import { Param } from '../../entities/base-filter.entity'; import { Param } from '../../entities/base-filter.entity';
import { joinRelationHelper } from 'src/core/helpers/query/join-relations.helper'; import { joinRelationHelper } from 'src/core/helpers/query/join-relations.helper';
import { STATUS } from 'src/core/strings/constants/base.constants';
export abstract class BaseIndexManager<Entity> extends BaseReadManager { export abstract class BaseIndexManager<Entity> extends BaseReadManager {
protected result: PaginationResponse<Entity>; protected result: PaginationResponse<Entity>;
@ -19,6 +20,7 @@ export abstract class BaseIndexManager<Entity> extends BaseReadManager {
} }
async process(): Promise<void> { async process(): Promise<void> {
const specificFilter = this.specificFilter;
const { joinRelations, selectRelations, countRelations } = this.relations; const { joinRelations, selectRelations, countRelations } = this.relations;
if (joinRelations?.length) if (joinRelations?.length)
@ -40,10 +42,30 @@ export abstract class BaseIndexManager<Entity> extends BaseReadManager {
if (this.selects?.length) this.queryBuilder.select(this.selects); if (this.selects?.length) this.queryBuilder.select(this.selects);
if (this.filterParam.statuses?.length > 0) {
const data = this.filterParam.statuses.map((status) => {
const statusData = status.includes("'")
? status.trim().replace(/'/g, "''").replace(/\s+/g, ' ')
: status.trim().replace(/\s+/g, ' ');
// jika searching status terdapat dalam enum, maka dia mencari specific data
// ? karena jika tidak, ketika dia search "active" maka "inactive" juga ikut
return `'${STATUS[statusData.toUpperCase()]}'` ?? `'%${statusData}%'`;
});
const exist = specificFilter.find((item) => item.isStatus);
if (!exist) {
specificFilter.push({
cols: `${this.tableName}.status::text`,
data: data,
});
}
}
new SpecificSearchFilter<Entity>( new SpecificSearchFilter<Entity>(
this.queryBuilder, this.queryBuilder,
this.tableName, this.tableName,
this.specificFilter, specificFilter,
).getFilter(); ).getFilter();
getOrderBy(this.filterParam, this.queryBuilder, this.tableName); getOrderBy(this.filterParam, this.queryBuilder, this.tableName);

View File

@ -9,6 +9,7 @@ export abstract class BaseUpdateStatusManager<Entity> extends BaseManager {
protected result: Entity; protected result: Entity;
protected oldData: Entity; protected oldData: Entity;
protected dataStatus: STATUS; protected dataStatus: STATUS;
protected relations = [];
protected duplicateColumn: string[]; protected duplicateColumn: string[];
abstract get entityTarget(): any; abstract get entityTarget(): any;
@ -22,6 +23,7 @@ export abstract class BaseUpdateStatusManager<Entity> extends BaseManager {
where: { where: {
id: this.dataId, id: this.dataId,
}, },
relations: this.relations,
}); });
this.oldData = _.cloneDeep(this.data); this.oldData = _.cloneDeep(this.data);

View File

@ -27,7 +27,7 @@ export abstract class BaseUpdateManager<Entity> extends BaseManager {
if (!this.oldData) { if (!this.oldData) {
throw new NotFoundException({ throw new NotFoundException({
statusCode: HttpStatus.NOT_FOUND, statusCode: HttpStatus.NOT_FOUND,
message: `Failed! Entity with id ${this.dataId} not found`, message: `Gagal! Data denga id ${this.dataId} tidak ditemukan`,
error: 'Entity Not Found', error: 'Entity Not Found',
}); });
} }
@ -102,7 +102,7 @@ export abstract class BaseUpdateManager<Entity> extends BaseManager {
this.eventBus.publishAll([ this.eventBus.publishAll([
new topic.topic({ new topic.topic({
id: data?.['id'] ?? topic?.data?.['id'], id: topic.data?.['id'] ?? this.dataId,
old: this.oldData, old: this.oldData,
data: data ?? topic.data, data: data ?? topic.data,
user: this.user, user: this.user,

View File

@ -4,9 +4,9 @@ import { BaseDataOrchestrator } from './base-data.orchestrator';
export abstract class BaseDataTransactionOrchestrator< export abstract class BaseDataTransactionOrchestrator<
Entity, Entity,
> extends BaseDataOrchestrator<Entity> { > extends BaseDataOrchestrator<Entity> {
abstract active(dataId: string): Promise<String>; abstract active(dataId: string): Promise<string>;
abstract confirm(dataId: string): Promise<String>; abstract confirm(dataId: string): Promise<string>;
abstract inactive(dataId: string): Promise<String>; abstract inactive(dataId: string): Promise<string>;
abstract batchConfirm(dataIds: string[]): Promise<BatchResult>; abstract batchConfirm(dataIds: string[]): Promise<BatchResult>;
abstract batchActive(dataIds: string[]): Promise<BatchResult>; abstract batchActive(dataIds: string[]): Promise<BatchResult>;
abstract batchInactive(dataIds: string[]): Promise<BatchResult>; abstract batchInactive(dataIds: string[]): Promise<BatchResult>;

View File

@ -3,6 +3,6 @@ import { BatchResult } from 'src/core/response/domain/ok-response.interface';
export abstract class BaseDataOrchestrator<Entity> { export abstract class BaseDataOrchestrator<Entity> {
abstract create(data: Entity): Promise<Entity>; abstract create(data: Entity): Promise<Entity>;
abstract update(dataId: string, data: Entity): Promise<Entity>; abstract update(dataId: string, data: Entity): Promise<Entity>;
abstract delete(dataId: string): Promise<String>; abstract delete(dataId: string): Promise<string>;
abstract batchDelete(dataIds: string[]): Promise<BatchResult>; abstract batchDelete(dataIds: string[]): Promise<BatchResult>;
} }

View File

@ -0,0 +1,4 @@
export class ChangePositionDto {
start: string;
end: string;
}

View File

@ -6,7 +6,9 @@ export enum STATUS {
DRAFT = 'draft', DRAFT = 'draft',
EXPIRED = 'expired', EXPIRED = 'expired',
INACTIVE = 'inactive', INACTIVE = 'inactive',
PARTIAL_REFUND = 'partial refund',
PENDING = 'pending', PENDING = 'pending',
PROCESS_REFUND = 'proses refund',
REFUNDED = 'refunded', REFUNDED = 'refunded',
REJECTED = 'rejected', REJECTED = 'rejected',
SETTLED = 'settled', SETTLED = 'settled',
@ -18,6 +20,16 @@ export enum ORDER_TYPE {
DESC = 'DESC', DESC = 'DESC',
} }
export const DAY = [
'minggu',
'senin',
'selasa',
'rabu',
'kamis',
'jumat',
'sabtu',
];
export enum CONNECTION_NAME { export enum CONNECTION_NAME {
DEFAULT = 'default', DEFAULT = 'default',
} }
@ -46,3 +58,5 @@ export const BLANK_USER = {
role: null, role: null,
user_privilege_id: null, user_privilege_id: null,
}; };
export const EMPTY_UUID = '00000000-0000-0000-0000-000000000000';

View File

@ -24,7 +24,7 @@ export interface validateRelations {
export interface columnUniques { export interface columnUniques {
column: string; column: string;
query?: Object; query?: any;
} }
export interface IEvent<Entity = any> { export interface IEvent<Entity = any> {

View File

@ -1,12 +1,18 @@
export enum MODULE_NAME { export enum MODULE_NAME {
BANNER = 'banners',
FAQ = 'faqs',
GATE = 'gates',
ITEM = 'items', ITEM = 'items',
ITEM_CATEGORY = 'item-categories', ITEM_CATEGORY = 'item-categories',
ITEM_RATE = 'item-rates', ITEM_RATE = 'item-rates',
NEWS = 'news',
PAYMENT_METHOD = 'payment-methods', PAYMENT_METHOD = 'payment-methods',
RECONCILIATION = 'reconciliations', RECONCILIATION = 'reconciliations',
REFUND = 'refunds',
SEASON_TYPE = 'season-types', SEASON_TYPE = 'season-types',
SEASON_PERIOD = 'season-periods', SEASON_PERIOD = 'season-periods',
TAX = 'taxes', TAX = 'taxes',
TERM_CONDITION = 'term_conditions',
TENANT = 'tenants', TENANT = 'tenants',
TRANSACTION = 'transactions', TRANSACTION = 'transactions',
USER = 'users', USER = 'users',

View File

@ -51,7 +51,6 @@ export const PrivilegeAdminConstant = [
menu_label: 'Rekonsiliasi', menu_label: 'Rekonsiliasi',
actions: [ actions: [
PrivilegeAction.VIEW, PrivilegeAction.VIEW,
PrivilegeAction.CREATE,
PrivilegeAction.CONFIRM, PrivilegeAction.CONFIRM,
PrivilegeAction.DELETE, PrivilegeAction.DELETE,
PrivilegeAction.CANCEL, PrivilegeAction.CANCEL,
@ -146,8 +145,8 @@ export const PrivilegePOSConstant = [
actions: [ actions: [
PrivilegeAction.VIEW, PrivilegeAction.VIEW,
PrivilegeAction.CREATE, PrivilegeAction.CREATE,
PrivilegeAction.DELETE,
PrivilegeAction.EDIT, PrivilegeAction.EDIT,
PrivilegeAction.CANCEL,
], ],
index: 14, index: 14,
}, },
@ -160,7 +159,7 @@ export const PrivilegePOSConstant = [
{ {
menu: 'BOOKING', menu: 'BOOKING',
menu_label: 'Pemesanan', menu_label: 'Pemesanan',
actions: [PrivilegeAction.VIEW, PrivilegeAction.CREATE], actions: [PrivilegeAction.VIEW],
index: 16, index: 16,
}, },
{ {
@ -175,4 +174,10 @@ export const PrivilegePOSConstant = [
actions: [PrivilegeAction.CREATE], actions: [PrivilegeAction.CREATE],
index: 18, index: 18,
}, },
{
menu: 'PRINT_RECEIPT',
menu_label: 'Print Receipt',
actions: [PrivilegeAction.CREATE],
index: 19,
},
]; ];

View File

@ -1,14 +1,22 @@
export enum TABLE_NAME { export enum TABLE_NAME {
BANNER = 'banners',
ERROR_LOG = 'log_errors', ERROR_LOG = 'log_errors',
FAQ = 'faqs',
ITEM = 'items', ITEM = 'items',
ITEM_CATEGORY = 'item_categories', ITEM_CATEGORY = 'item_categories',
ITEM_RATE = 'item_rates', ITEM_RATE = 'item_rates',
GATE = 'gates',
LOG = 'logs', LOG = 'logs',
LOG_POS = 'logs_pos',
NEWS = 'news',
PAYMENT_METHOD = 'payment_methods', PAYMENT_METHOD = 'payment_methods',
PRICE_FORMULA = 'price_formulas', PRICE_FORMULA = 'price_formulas',
REFUND = 'refunds',
REFUND_ITEM = 'refund_items',
SEASON_TYPE = 'season_types', SEASON_TYPE = 'season_types',
SEASON_PERIOD = 'season_periods', SEASON_PERIOD = 'season_periods',
TAX = 'taxes', TAX = 'taxes',
TERM_CONDITION = 'term_conditions',
TENANT = 'tenants', TENANT = 'tenants',
TRANSACTION = 'transactions', TRANSACTION = 'transactions',
TRANSACTION_ITEM = 'transaction_items', TRANSACTION_ITEM = 'transaction_items',

View File

@ -9,7 +9,7 @@ import { MODULE_NAME } from 'src/core/strings/constants/module.constants';
import { Public } from 'src/core/guards'; import { Public } from 'src/core/guards';
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - read`) @ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - read`)
@Controller(`v1/${MODULE_NAME.{{constantCase name}}}`) @Controller(`v1/${MODULE_NAME.{{constantCase name}} }`)
@Public(false) @Public(false)
@ApiBearerAuth('JWT') @ApiBearerAuth('JWT')
export class {{pascalCase name}}ReadController { export class {{pascalCase name}}ReadController {

View File

@ -17,7 +17,7 @@ import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto'
import { Public } from 'src/core/guards'; import { Public } from 'src/core/guards';
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`) @ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`)
@Controller(`v1/${MODULE_NAME.{{constantCase name}}}`) @Controller(`v1/${MODULE_NAME.{{constantCase name}} }`)
@Public(false) @Public(false)
@ApiBearerAuth('JWT') @ApiBearerAuth('JWT')
export class {{pascalCase name}}DataController { export class {{pascalCase name}}DataController {
@ -36,7 +36,7 @@ export class {{pascalCase name}}DataController {
} }
@Patch(':id/active') @Patch(':id/active')
async active(@Param('id') dataId: string): Promise<String> { async active(@Param('id') dataId: string): Promise<string> {
return await this.orchestrator.active(dataId); return await this.orchestrator.active(dataId);
} }
@ -46,7 +46,7 @@ export class {{pascalCase name}}DataController {
} }
@Patch(':id/confirm') @Patch(':id/confirm')
async confirm(@Param('id') dataId: string): Promise<String> { async confirm(@Param('id') dataId: string): Promise<string> {
return await this.orchestrator.confirm(dataId); return await this.orchestrator.confirm(dataId);
} }
@ -56,7 +56,7 @@ export class {{pascalCase name}}DataController {
} }
@Patch(':id/inactive') @Patch(':id/inactive')
async inactive(@Param('id') dataId: string): Promise<String> { async inactive(@Param('id') dataId: string): Promise<string> {
return await this.orchestrator.inactive(dataId); return await this.orchestrator.inactive(dataId);
} }
@ -74,7 +74,7 @@ export class {{pascalCase name}}DataController {
} }
@Delete(':id') @Delete(':id')
async delete(@Param('id') dataId: string): Promise<String> { async delete(@Param('id') dataId: string): Promise<string> {
return await this.orchestrator.delete(dataId); return await this.orchestrator.delete(dataId);
} }
} }

View File

@ -16,7 +16,7 @@ import {
import { Public } from 'src/core/guards'; import { Public } from 'src/core/guards';
@ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`) @ApiTags(`${MODULE_NAME.{{constantCase name}}.split('-').join(' ')} - data`)
@Controller(`v1/${MODULE_NAME.{{constantCase name}}}`) @Controller(`v1/${MODULE_NAME.{{constantCase name}} }`)
@Public(false) @Public(false)
@ApiBearerAuth('JWT') @ApiBearerAuth('JWT')
export class {{pascalCase name}}DataController { export class {{pascalCase name}}DataController {
@ -43,7 +43,7 @@ import {
} }
@Delete(':id') @Delete(':id')
async delete(@Param('id') dataId: string): Promise<String> { async delete(@Param('id') dataId: string): Promise<string> {
return await this.orchestrator.delete(dataId); return await this.orchestrator.delete(dataId);
} }
} }

View File

@ -48,7 +48,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
return this.updateManager.getResult(); return this.updateManager.getResult();
} }
async delete(dataId): Promise<String> { async delete(dataId): Promise<string> {
this.deleteManager.setData(dataId); this.deleteManager.setData(dataId);
this.deleteManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}}); this.deleteManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
await this.deleteManager.execute(); await this.deleteManager.execute();
@ -65,7 +65,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
return this.batchDeleteManager.getResult(); return this.batchDeleteManager.getResult();
} }
async active(dataId): Promise<String> { async active(dataId): Promise<string> {
this.activeManager.setData(dataId, STATUS.ACTIVE); this.activeManager.setData(dataId, STATUS.ACTIVE);
this.activeManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}}); this.activeManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
await this.activeManager.execute(); await this.activeManager.execute();
@ -82,7 +82,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
return this.batchActiveManager.getResult(); return this.batchActiveManager.getResult();
} }
async confirm(dataId): Promise<String> { async confirm(dataId): Promise<string> {
this.confirmManager.setData(dataId, STATUS.ACTIVE); this.confirmManager.setData(dataId, STATUS.ACTIVE);
this.confirmManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}}); this.confirmManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
await this.confirmManager.execute(); await this.confirmManager.execute();
@ -99,7 +99,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
return this.batchConfirmManager.getResult(); return this.batchConfirmManager.getResult();
} }
async inactive(dataId): Promise<String> { async inactive(dataId): Promise<string> {
this.inactiveManager.setData(dataId, STATUS.INACTIVE); this.inactiveManager.setData(dataId, STATUS.INACTIVE);
this.inactiveManager.setService( this.inactiveManager.setService(
this.serviceData, this.serviceData,

View File

@ -36,7 +36,7 @@ export class {{pascalCase name}}DataOrchestrator extends Base{{pascalCase orches
return this.updateManager.getResult(); return this.updateManager.getResult();
} }
async delete(dataId): Promise<String> { async delete(dataId): Promise<string> {
this.deleteManager.setData(dataId); this.deleteManager.setData(dataId);
this.deleteManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}}); this.deleteManager.setService(this.serviceData, TABLE_NAME.{{constantCase name}});
await this.deleteManager.execute(); await this.deleteManager.execute();

View File

@ -1,18 +1,29 @@
import { MigrationInterface, QueryRunner } from "typeorm"; import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateTableTransaction1720436852936 implements MigrationInterface { export class UpdateTableTransaction1720436852936 implements MigrationInterface {
name = 'UpdateTableTransaction1720436852936' name = 'UpdateTableTransaction1720436852936';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "transaction_taxes" ADD "tax_total_value" numeric`); await queryRunner.query(
await queryRunner.query(`ALTER TABLE "transaction_taxes" DROP COLUMN "taxt_value"`); `ALTER TABLE "transaction_taxes" ADD "tax_total_value" numeric`,
await queryRunner.query(`ALTER TABLE "transaction_taxes" ADD "taxt_value" numeric`); );
} await queryRunner.query(
`ALTER TABLE "transaction_taxes" DROP COLUMN "taxt_value"`,
public async down(queryRunner: QueryRunner): Promise<void> { );
await queryRunner.query(`ALTER TABLE "transaction_taxes" DROP COLUMN "taxt_value"`); await queryRunner.query(
await queryRunner.query(`ALTER TABLE "transaction_taxes" ADD "taxt_value" character varying`); `ALTER TABLE "transaction_taxes" ADD "taxt_value" numeric`,
await queryRunner.query(`ALTER TABLE "transaction_taxes" DROP COLUMN "tax_total_value"`); );
} }
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transaction_taxes" DROP COLUMN "taxt_value"`,
);
await queryRunner.query(
`ALTER TABLE "transaction_taxes" ADD "taxt_value" character varying`,
);
await queryRunner.query(
`ALTER TABLE "transaction_taxes" DROP COLUMN "tax_total_value"`,
);
}
} }

View File

@ -0,0 +1,27 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateTableTransaction1720767689625 implements MigrationInterface {
name = 'UpdateTableTransaction1720767689625';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transaction_items" ADD "qty_remaining" integer`,
);
await queryRunner.query(`ALTER TABLE "transaction_items" ADD "taxes" json`);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "payment_total_dpp" numeric`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "payment_total_dpp"`,
);
await queryRunner.query(
`ALTER TABLE "transaction_items" DROP COLUMN "taxes"`,
);
await queryRunner.query(
`ALTER TABLE "transaction_items" DROP COLUMN "qty_remaining"`,
);
}
}

View File

@ -0,0 +1,45 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class Refund1720768975877 implements MigrationInterface {
name = 'Refund1720768975877';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."refunds_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`CREATE TYPE "public"."refunds_type_enum" AS ENUM('pengembalian booking', 'pengembalian wahana')`,
);
await queryRunner.query(
`CREATE TABLE "refunds" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."refunds_status_enum" NOT NULL DEFAULT 'draft', "type" "public"."refunds_type_enum" NOT NULL DEFAULT 'pengembalian booking', "code" character varying, "request_date" date, "refund_date" date, "refund_total" numeric, "bank_name" character varying, "bank_account_name" character varying, "bank_account_number" character varying, "transaction_id" uuid, CONSTRAINT "REL_8bb3b7579f49990d2e77684acd" UNIQUE ("transaction_id"), CONSTRAINT "PK_5106efb01eeda7e49a78b869738" PRIMARY KEY ("id"))`,
);
await queryRunner.query(
`CREATE TABLE "refund_items" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "qty_refund" numeric, "refund_total" numeric, "refund_item_id" uuid, "transaction_item_id" uuid, CONSTRAINT "REL_07b481a163c219f5de8fb1c90b" UNIQUE ("transaction_item_id"), CONSTRAINT "PK_ef892918375a6101948b90f1140" PRIMARY KEY ("id"))`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ADD CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" ADD CONSTRAINT "FK_2a4bd60fb8a9c37f902f4f3da67" FOREIGN KEY ("refund_item_id") REFERENCES "refunds"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" ADD CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3" FOREIGN KEY ("transaction_item_id") REFERENCES "transaction_items"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "refund_items" DROP CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3"`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" DROP CONSTRAINT "FK_2a4bd60fb8a9c37f902f4f3da67"`,
);
await queryRunner.query(
`ALTER TABLE "refunds" DROP CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4"`,
);
await queryRunner.query(`DROP TABLE "refund_items"`);
await queryRunner.query(`DROP TABLE "refunds"`);
await queryRunner.query(`DROP TYPE "public"."refunds_type_enum"`);
await queryRunner.query(`DROP TYPE "public"."refunds_status_enum"`);
}
}

View File

@ -0,0 +1,461 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateEnumStatus1720774145470 implements MigrationInterface {
name = 'UpdateEnumStatus1720774145470';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TYPE "public"."item_categories_status_enum" RENAME TO "item_categories_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."item_categories_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "item_categories" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "item_categories" ALTER COLUMN "status" TYPE "public"."item_categories_status_enum" USING "status"::"text"::"public"."item_categories_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "item_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."item_categories_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."season_types_status_enum" RENAME TO "season_types_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."season_types_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "season_types" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "season_types" ALTER COLUMN "status" TYPE "public"."season_types_status_enum" USING "status"::"text"::"public"."season_types_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "season_types" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."season_types_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."season_periods_status_enum" RENAME TO "season_periods_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."season_periods_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "season_periods" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "season_periods" ALTER COLUMN "status" TYPE "public"."season_periods_status_enum" USING "status"::"text"::"public"."season_periods_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "season_periods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."season_periods_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."items_status_enum" RENAME TO "items_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."items_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "items" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "items" ALTER COLUMN "status" TYPE "public"."items_status_enum" USING "status"::"text"::"public"."items_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "items" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."items_status_enum_old"`);
await queryRunner.query(
`ALTER TYPE "public"."users_status_enum" RENAME TO "users_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."users_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "users" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "users" ALTER COLUMN "status" TYPE "public"."users_status_enum" USING "status"::"text"::"public"."users_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "users" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."users_status_enum_old"`);
await queryRunner.query(
`ALTER TYPE "public"."user_privileges_status_enum" RENAME TO "user_privileges_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."user_privileges_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "user_privileges" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "user_privileges" ALTER COLUMN "status" TYPE "public"."user_privileges_status_enum" USING "status"::"text"::"public"."user_privileges_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "user_privileges" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."user_privileges_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."refunds_status_enum" RENAME TO "refunds_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."refunds_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ALTER COLUMN "status" TYPE "public"."refunds_status_enum" USING "status"::"text"::"public"."refunds_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."refunds_status_enum_old"`);
await queryRunner.query(
`ALTER TYPE "public"."transactions_status_enum" RENAME TO "transactions_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "status" TYPE "public"."transactions_status_enum" USING "status"::"text"::"public"."transactions_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."transactions_reconciliation_status_enum" RENAME TO "transactions_reconciliation_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_reconciliation_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" TYPE "public"."transactions_reconciliation_status_enum" USING "reconciliation_status"::"text"::"public"."transactions_reconciliation_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_reconciliation_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."transactions_sending_invoice_status_enum" RENAME TO "transactions_sending_invoice_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_sending_invoice_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "sending_invoice_status" TYPE "public"."transactions_sending_invoice_status_enum" USING "sending_invoice_status"::"text"::"public"."transactions_sending_invoice_status_enum"`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_sending_invoice_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."transactions_sending_qr_status_enum" RENAME TO "transactions_sending_qr_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_sending_qr_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "sending_qr_status" TYPE "public"."transactions_sending_qr_status_enum" USING "sending_qr_status"::"text"::"public"."transactions_sending_qr_status_enum"`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_sending_qr_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."vip_categories_status_enum" RENAME TO "vip_categories_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."vip_categories_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "vip_categories" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "vip_categories" ALTER COLUMN "status" TYPE "public"."vip_categories_status_enum" USING "status"::"text"::"public"."vip_categories_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "vip_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."vip_categories_status_enum_old"`,
);
await queryRunner.query(
`ALTER TYPE "public"."taxes_status_enum" RENAME TO "taxes_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."taxes_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "taxes" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "taxes" ALTER COLUMN "status" TYPE "public"."taxes_status_enum" USING "status"::"text"::"public"."taxes_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "taxes" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."taxes_status_enum_old"`);
await queryRunner.query(
`ALTER TYPE "public"."payment_methods_status_enum" RENAME TO "payment_methods_status_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."payment_methods_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "payment_methods" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "payment_methods" ALTER COLUMN "status" TYPE "public"."payment_methods_status_enum" USING "status"::"text"::"public"."payment_methods_status_enum"`,
);
await queryRunner.query(
`ALTER TABLE "payment_methods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."payment_methods_status_enum_old"`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."payment_methods_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "payment_methods" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "payment_methods" ALTER COLUMN "status" TYPE "public"."payment_methods_status_enum_old" USING "status"::"text"::"public"."payment_methods_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "payment_methods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."payment_methods_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."payment_methods_status_enum_old" RENAME TO "payment_methods_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."taxes_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "taxes" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "taxes" ALTER COLUMN "status" TYPE "public"."taxes_status_enum_old" USING "status"::"text"::"public"."taxes_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "taxes" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."taxes_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."taxes_status_enum_old" RENAME TO "taxes_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."vip_categories_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "vip_categories" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "vip_categories" ALTER COLUMN "status" TYPE "public"."vip_categories_status_enum_old" USING "status"::"text"::"public"."vip_categories_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "vip_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."vip_categories_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."vip_categories_status_enum_old" RENAME TO "vip_categories_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_sending_qr_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "sending_qr_status" TYPE "public"."transactions_sending_qr_status_enum_old" USING "sending_qr_status"::"text"::"public"."transactions_sending_qr_status_enum_old"`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_sending_qr_status_enum"`,
);
await queryRunner.query(
`ALTER TYPE "public"."transactions_sending_qr_status_enum_old" RENAME TO "transactions_sending_qr_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_sending_invoice_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "sending_invoice_status" TYPE "public"."transactions_sending_invoice_status_enum_old" USING "sending_invoice_status"::"text"::"public"."transactions_sending_invoice_status_enum_old"`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_sending_invoice_status_enum"`,
);
await queryRunner.query(
`ALTER TYPE "public"."transactions_sending_invoice_status_enum_old" RENAME TO "transactions_sending_invoice_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_reconciliation_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" TYPE "public"."transactions_reconciliation_status_enum_old" USING "reconciliation_status"::"text"::"public"."transactions_reconciliation_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "reconciliation_status" SET DEFAULT 'draft'`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_reconciliation_status_enum"`,
);
await queryRunner.query(
`ALTER TYPE "public"."transactions_reconciliation_status_enum_old" RENAME TO "transactions_reconciliation_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."transactions_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "status" TYPE "public"."transactions_status_enum_old" USING "status"::"text"::"public"."transactions_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."transactions_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."transactions_status_enum_old" RENAME TO "transactions_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."refunds_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ALTER COLUMN "status" TYPE "public"."refunds_status_enum_old" USING "status"::"text"::"public"."refunds_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."refunds_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."refunds_status_enum_old" RENAME TO "refunds_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."user_privileges_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "user_privileges" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "user_privileges" ALTER COLUMN "status" TYPE "public"."user_privileges_status_enum_old" USING "status"::"text"::"public"."user_privileges_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "user_privileges" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."user_privileges_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."user_privileges_status_enum_old" RENAME TO "user_privileges_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."users_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "users" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "users" ALTER COLUMN "status" TYPE "public"."users_status_enum_old" USING "status"::"text"::"public"."users_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "users" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."users_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."users_status_enum_old" RENAME TO "users_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."items_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "items" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "items" ALTER COLUMN "status" TYPE "public"."items_status_enum_old" USING "status"::"text"::"public"."items_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "items" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."items_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."items_status_enum_old" RENAME TO "items_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."season_periods_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "season_periods" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "season_periods" ALTER COLUMN "status" TYPE "public"."season_periods_status_enum_old" USING "status"::"text"::"public"."season_periods_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "season_periods" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."season_periods_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."season_periods_status_enum_old" RENAME TO "season_periods_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."season_types_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "season_types" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "season_types" ALTER COLUMN "status" TYPE "public"."season_types_status_enum_old" USING "status"::"text"::"public"."season_types_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "season_types" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."season_types_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."season_types_status_enum_old" RENAME TO "season_types_status_enum"`,
);
await queryRunner.query(
`CREATE TYPE "public"."item_categories_status_enum_old" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`ALTER TABLE "item_categories" ALTER COLUMN "status" DROP DEFAULT`,
);
await queryRunner.query(
`ALTER TABLE "item_categories" ALTER COLUMN "status" TYPE "public"."item_categories_status_enum_old" USING "status"::"text"::"public"."item_categories_status_enum_old"`,
);
await queryRunner.query(
`ALTER TABLE "item_categories" ALTER COLUMN "status" SET DEFAULT 'draft'`,
);
await queryRunner.query(`DROP TYPE "public"."item_categories_status_enum"`);
await queryRunner.query(
`ALTER TYPE "public"."item_categories_status_enum_old" RENAME TO "item_categories_status_enum"`,
);
}
}

View File

@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class Gate1721024987609 implements MigrationInterface {
name = 'Gate1721024987609';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."gates_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`CREATE TYPE "public"."gates_type_enum" AS ENUM('gate masuk', 'gate keluar')`,
);
await queryRunner.query(
`CREATE TABLE "gates" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."gates_status_enum" NOT NULL DEFAULT 'draft', "type" "public"."gates_type_enum" NOT NULL DEFAULT 'gate masuk', "code" character varying, "note" text, "item_id" uuid, CONSTRAINT "PK_2dd58a77462dd2c5695ec4a7975" PRIMARY KEY ("id"))`,
);
await queryRunner.query(
`ALTER TABLE "gates" ADD CONSTRAINT "FK_29f020cd153bb079722bcbee830" FOREIGN KEY ("item_id") REFERENCES "items"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "gates" DROP CONSTRAINT "FK_29f020cd153bb079722bcbee830"`,
);
await queryRunner.query(`DROP TABLE "gates"`);
await queryRunner.query(`DROP TYPE "public"."gates_type_enum"`);
await queryRunner.query(`DROP TYPE "public"."gates_status_enum"`);
}
}

View File

@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class TermCondition1721029248635 implements MigrationInterface {
name = 'TermCondition1721029248635';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."term_conditions_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`CREATE TABLE "term_conditions" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."term_conditions_status_enum" NOT NULL DEFAULT 'draft', "title" character varying, "description" text, CONSTRAINT "PK_fc92769e487820f24ed68337feb" PRIMARY KEY ("id"))`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "term_conditions"`);
await queryRunner.query(`DROP TYPE "public"."term_conditions_status_enum"`);
}
}

View File

@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class FrequentlyAskQuestion1721029454627 implements MigrationInterface {
name = 'FrequentlyAskQuestion1721029454627';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."faqs_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`CREATE TABLE "faqs" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."faqs_status_enum" NOT NULL DEFAULT 'draft', "title" character varying, "description" text, CONSTRAINT "PK_2ddf4f2c910f8e8fa2663a67bf0" PRIMARY KEY ("id"))`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "faqs"`);
await queryRunner.query(`DROP TYPE "public"."faqs_status_enum"`);
}
}

View File

@ -0,0 +1,17 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateRefund1721031712642 implements MigrationInterface {
name = 'UpdateRefund1721031712642';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "refunds" ADD "refund_sub_total" numeric`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "refunds" DROP COLUMN "refund_sub_total"`,
);
}
}

View File

@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class News1721109817371 implements MigrationInterface {
name = 'News1721109817371';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."news_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`CREATE TABLE "news" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."news_status_enum" NOT NULL DEFAULT 'draft', "image_url" character varying, "title" character varying, "teaser" character varying, "description" character varying, CONSTRAINT "PK_39a43dfcb6007180f04aff2357e" PRIMARY KEY ("id"))`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "news"`);
await queryRunner.query(`DROP TYPE "public"."news_status_enum"`);
}
}

View File

@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class Banner1721111093665 implements MigrationInterface {
name = 'Banner1721111093665';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."banners_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`,
);
await queryRunner.query(
`CREATE TABLE "banners" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."banners_status_enum" NOT NULL DEFAULT 'draft', "image_url" character varying, "title" character varying, "link" character varying, CONSTRAINT "PK_e9b186b959296fcb940790d31c3" PRIMARY KEY ("id"))`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "banners"`);
await queryRunner.query(`DROP TYPE "public"."banners_status_enum"`);
}
}

View File

@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateTableTransactions1721216510569
implements MigrationInterface
{
name = 'UpdateTableTransactions1721216510569';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" ADD "payment_midtrans_token" character varying`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "payment_midtrans_url" character varying`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "payment_midtrans_url"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "payment_midtrans_token"`,
);
}
}

View File

@ -0,0 +1,21 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateSortColumn1721284172572 implements MigrationInterface {
name = 'UpdateSortColumn1721284172572';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "term_conditions" ADD "sort_order" integer NOT NULL DEFAULT '0'`,
);
await queryRunner.query(
`ALTER TABLE "faqs" ADD "sort_order" integer NOT NULL DEFAULT '0'`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "faqs" DROP COLUMN "sort_order"`);
await queryRunner.query(
`ALTER TABLE "term_conditions" DROP COLUMN "sort_order"`,
);
}
}

View File

@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateColumnTransaction1721385120750
implements MigrationInterface
{
name = 'UpdateColumnTransaction1721385120750';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "discount_percentage"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "discount_percentage" numeric`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "discount_percentage"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "discount_percentage" integer`,
);
}
}

View File

@ -0,0 +1,17 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateImageColumnItem1721647955446 implements MigrationInterface {
name = 'UpdateImageColumnItem1721647955446';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "items" RENAME COLUMN "image" TO "image_url"`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "items" RENAME COLUMN "image_url" TO "image"`,
);
}
}

View File

@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class PosLog1721736523991 implements MigrationInterface {
name = 'PosLog1721736523991';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "logs_pos" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "type" character varying NOT NULL DEFAULT 'cash withdrawal', "pos_number" bigint, "total_balance" numeric, "created_at" bigint, "creator_name" character varying, "creator_id" character varying, CONSTRAINT "PK_60df825558a6b6881d7ad770d26" PRIMARY KEY ("id"))`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "logs_pos"`);
}
}

View File

@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class AddCalendarColumnTransaction1721892389807
implements MigrationInterface
{
name = 'AddCalendarColumnTransaction1721892389807';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" ADD "calendar_id" character varying`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "calendar_link" character varying`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "calendar_id"`,
);
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "calendar_link"`,
);
}
}

View File

@ -0,0 +1,27 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class AddColumnToRefundTable1722318939681 implements MigrationInterface {
name = 'AddColumnToRefundTable1722318939681';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."refunds_refund_reason_type_enum" AS ENUM('weather', 'ride malfunction', 'other')`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ADD "refund_reason_type" "public"."refunds_refund_reason_type_enum" NOT NULL DEFAULT 'ride malfunction'`,
);
await queryRunner.query(`ALTER TABLE "refunds" ADD "refund_reason" text`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "refunds" DROP COLUMN "refund_reason"`,
);
await queryRunner.query(
`ALTER TABLE "refunds" DROP COLUMN "refund_reason_type"`,
);
await queryRunner.query(
`DROP TYPE "public"."refunds_refund_reason_type_enum"`,
);
}
}

View File

@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateColumnToTransactionTable1722334034920
implements MigrationInterface
{
name = 'UpdateColumnToTransactionTable1722334034920';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transaction_items" ADD "qr_image_url" character varying`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "payment_code" character varying`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "payment_code"`,
);
await queryRunner.query(
`ALTER TABLE "transaction_items" DROP COLUMN "qr_image_url"`,
);
}
}

View File

@ -0,0 +1,21 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class PosLogAddColumnDownBy1722509262047 implements MigrationInterface {
name = 'PosLogAddColumnDownBy1722509262047';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "logs_pos" ADD "drawn_by_name" character varying`,
);
await queryRunner.query(
`ALTER TABLE "logs_pos" ADD "drawn_by_id" character varying`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "logs_pos" DROP COLUMN "drawn_by_id"`);
await queryRunner.query(
`ALTER TABLE "logs_pos" DROP COLUMN "drawn_by_name"`,
);
}
}

View File

@ -0,0 +1,49 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateRelationTableTransaction1722581313837
implements MigrationInterface
{
name = 'UpdateRelationTableTransaction1722581313837';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "refunds" DROP CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4"`,
);
await queryRunner.query(
`ALTER TABLE "refunds" DROP CONSTRAINT "REL_8bb3b7579f49990d2e77684acd"`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" DROP CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3"`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" DROP CONSTRAINT "REL_07b481a163c219f5de8fb1c90b"`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ADD CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" ADD CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3" FOREIGN KEY ("transaction_item_id") REFERENCES "transaction_items"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "refund_items" DROP CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3"`,
);
await queryRunner.query(
`ALTER TABLE "refunds" DROP CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4"`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" ADD CONSTRAINT "REL_07b481a163c219f5de8fb1c90b" UNIQUE ("transaction_item_id")`,
);
await queryRunner.query(
`ALTER TABLE "refund_items" ADD CONSTRAINT "FK_07b481a163c219f5de8fb1c90b3" FOREIGN KEY ("transaction_item_id") REFERENCES "transaction_items"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ADD CONSTRAINT "REL_8bb3b7579f49990d2e77684acd" UNIQUE ("transaction_id")`,
);
await queryRunner.query(
`ALTER TABLE "refunds" ADD CONSTRAINT "FK_8bb3b7579f49990d2e77684acd4" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
}
}

View File

@ -0,0 +1,17 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateTypeColumnItemTable1722587128195
implements MigrationInterface
{
name = 'UpdateTypeColumnItemTable1722587128195';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "items" DROP COLUMN "sales_margin"`);
await queryRunner.query(`ALTER TABLE "items" ADD "sales_margin" numeric`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "items" DROP COLUMN "sales_margin"`);
await queryRunner.query(`ALTER TABLE "items" ADD "sales_margin" integer`);
}
}

View File

@ -0,0 +1,23 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateTableTransaction1722595038215 implements MigrationInterface {
name = 'UpdateTableTransaction1722595038215';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."transactions_payment_type_counter_enum" AS ENUM('midtrans', 'bank transfer', 'qris', 'counter', 'cash', 'credit card', 'debit', 'e-money')`,
);
await queryRunner.query(
`ALTER TABLE "transactions" ADD "payment_type_counter" "public"."transactions_payment_type_counter_enum"`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "payment_type_counter"`,
);
await queryRunner.query(
`DROP TYPE "public"."transactions_payment_type_counter_enum"`,
);
}
}

View File

@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class AddColumnToTransactionsTable1722693550579
implements MigrationInterface
{
name = 'AddColumnToTransactionsTable1722693550579';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" ADD "booking_date_before" date`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "transactions" DROP COLUMN "booking_date_before"`,
);
}
}

View File

@ -29,8 +29,6 @@ export class SeedDefaultFormula implements Seeder {
.into(SalesPriceFormulaModel) .into(SalesPriceFormulaModel)
.values([sales_formula, profit_formula]) .values([sales_formula, profit_formula])
.execute(); .execute();
} catch (error) { } catch (error) {}
console.log(error, 'er');
}
} }
} }

View File

@ -133,7 +133,7 @@ export class LoginManager extends BaseCustomManager<UserEntity> {
throwError() { throwError() {
throw new UnauthorizedException({ throw new UnauthorizedException({
statusCode: HttpStatus.UNAUTHORIZED, statusCode: HttpStatus.UNAUTHORIZED,
message: `Failed! You have entered an invalid username or password`, message: `Gagal! username atau password tidak sesuai`,
error: 'Unauthorized', error: 'Unauthorized',
}); });
} }

View File

@ -5,13 +5,17 @@ import { STATUS } from 'src/core/strings/constants/base.constants';
import { ItemType } from 'src/modules/item-related/item-category/constants'; import { ItemType } from 'src/modules/item-related/item-category/constants';
import { LimitType } from 'src/modules/item-related/item/constants'; import { LimitType } from 'src/modules/item-related/item/constants';
import { PaymentMethodType } from 'src/modules/transaction/payment-method/constants'; import { PaymentMethodType } from 'src/modules/transaction/payment-method/constants';
import {
RefundReasonType,
RefundType,
} from 'src/modules/transaction/refund/constants';
import { GateType } from 'src/modules/web-information/gate/constants';
import { InvoiceType } from '../../export/constants';
@ApiTags('configuration - constant') @ApiTags('configuration - constant')
@Controller('v1/constant') @Controller('v1/constant')
@Public(true) @Public(true)
export class ConstantController { export class ConstantController {
constructor() {}
@Get('master-data-status') @Get('master-data-status')
async masterDataStatus(): Promise<any> { async masterDataStatus(): Promise<any> {
return [STATUS.ACTIVE, STATUS.DRAFT, STATUS.INACTIVE]; return [STATUS.ACTIVE, STATUS.DRAFT, STATUS.INACTIVE];
@ -46,4 +50,24 @@ export class ConstantController {
async transactionType(): Promise<any> { async transactionType(): Promise<any> {
return ['counter', 'admin', 'online']; return ['counter', 'admin', 'online'];
} }
@Get('refund-type')
async refundType(): Promise<any> {
return Object.values(RefundType);
}
@Get('refund-reason-type')
async refundReasonType(): Promise<any> {
return Object.values(RefundReasonType);
}
@Get('gate-type')
async gateType(): Promise<any> {
return Object.values(GateType);
}
@Get('invoice-type')
async invoiceType(): Promise<any> {
return Object.values(InvoiceType);
}
} }

View File

@ -1 +1,6 @@
export const DatabaseListen = ['transaction']; export const DatabaseListen = [
'transaction',
'vip_code',
'pos_activity',
'pos_cash_activity',
];

View File

@ -17,10 +17,13 @@ import {
} from './domain/managers/season-period.handler'; } from './domain/managers/season-period.handler';
import { import {
ItemDeletedHandler, ItemDeletedHandler,
ItemPriceUpdatedHandler,
ItemRateUpdatedHandler,
ItemUpdatedHandler, ItemUpdatedHandler,
} from './domain/managers/item.handler'; } from './domain/managers/item.handler';
import { import {
UserDeletedHandler, UserDeletedHandler,
UserPrivilegeUpdateHandler,
UserUpdatedHandler, UserUpdatedHandler,
} from './domain/managers/user.handler'; } from './domain/managers/user.handler';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
@ -37,6 +40,7 @@ import { TransactionDataService } from 'src/modules/transaction/transaction/data
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
import { TransactionTaxModel } from 'src/modules/transaction/transaction/data/models/transaction-tax.model'; import { TransactionTaxModel } from 'src/modules/transaction/transaction/data/models/transaction-tax.model';
import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model'; import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model';
import { VipCodeCreatedHandler } from './domain/managers/vip-code.handler';
@Module({ @Module({
imports: [ imports: [
@ -59,14 +63,18 @@ import { TransactionItemModel } from 'src/modules/transaction/transaction/data/m
BookingDeletedEvent, BookingDeletedEvent,
PaymentMethodDeletedHandler, PaymentMethodDeletedHandler,
PaymentMethodUpdatedHandler, PaymentMethodUpdatedHandler,
VipCodeCreatedHandler,
VipCategoryDeletedHandler, VipCategoryDeletedHandler,
VipCategoryUpdatedHandler, VipCategoryUpdatedHandler,
SeasonPeriodDeletedHandler, SeasonPeriodDeletedHandler,
SeasonPeriodUpdatedHandler, SeasonPeriodUpdatedHandler,
ItemUpdatedHandler, ItemUpdatedHandler,
ItemDeletedHandler, ItemDeletedHandler,
ItemRateUpdatedHandler,
ItemPriceUpdatedHandler,
UserDeletedHandler, UserDeletedHandler,
UserUpdatedHandler, UserUpdatedHandler,
UserPrivilegeUpdateHandler,
TransactionDataService, TransactionDataService,
UserDataService, UserDataService,

View File

@ -1,21 +1,32 @@
import { Injectable } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { DatabaseListen } from '../../constants'; import { DatabaseListen } from '../../constants';
import { EventBus } from '@nestjs/cqrs'; import { EventBus } from '@nestjs/cqrs';
import { ChangeDocEvent } from '../../domain/events/change-doc.event'; import { ChangeDocEvent } from '../../domain/events/change-doc.event';
import { ConfigService } from '@nestjs/config';
import * as Nano from 'nano';
@Injectable() @Injectable()
export class CouchService { export class CouchService {
constructor(private eventBus: EventBus) {} constructor(
private eventBus: EventBus,
private configService: ConfigService,
) {}
get nanoInstance() {
const couchConfiguration = this.configService.get<string>('COUCHDB_CONFIG');
return Nano(couchConfiguration);
}
async onModuleInit() { async onModuleInit() {
const nano = require('nano')('http://root:password@172.10.10.2:5970'); const nano = this.nanoInstance;
for (const database of DatabaseListen) { for (const database of DatabaseListen) {
const db = nano.db.use(database); const db = nano.db.use(database);
db.changesReader.start({ includeDocs: true }).on('change', (change) => { db.changesReader.start({ includeDocs: true }).on('change', (change) => {
this.changeDoc(change, database); this.changeDoc(change, database);
}); });
console.log(`start listen database ${database}`); Logger.log(`start listen database ${database}`, 'CouchService');
} }
} }
@ -31,7 +42,7 @@ export class CouchService {
public async createDoc(data, database) { public async createDoc(data, database) {
try { try {
const nano = require('nano')('http://root:password@172.10.10.2:5970'); const nano = this.nanoInstance;
const db = nano.use(database); const db = nano.use(database);
return await db.insert(data); return await db.insert(data);
} catch (error) {} } catch (error) {}
@ -39,7 +50,7 @@ export class CouchService {
public async deleteDoc(data, database) { public async deleteDoc(data, database) {
try { try {
const nano = require('nano')('http://root:password@172.10.10.2:5970'); const nano = this.nanoInstance;
const db = nano.use(database); const db = nano.use(database);
const result = await db.get(data.id); const result = await db.get(data.id);
await db.destroy(data.id, result._rev); await db.destroy(data.id, result._rev);
@ -48,10 +59,9 @@ export class CouchService {
public async updateDoc(data, database) { public async updateDoc(data, database) {
try { try {
const nano = require('nano')('http://root:password@172.10.10.2:5970'); const nano = this.nanoInstance;
const db = nano.use(database); const db = nano.use(database);
const result = await db.get(data.id); const result = await db.get(data.id);
console.log(result, 'dsa');
await db.insert({ await db.insert({
...data, ...data,
_rev: result._rev, _rev: result._rev,

View File

@ -20,7 +20,7 @@ export class BookingDeletedEvent
_id: event.data.id, _id: event.data.id,
...event.data.data, ...event.data.data,
}, },
'item', 'booking',
); );
} }
} }
@ -38,36 +38,41 @@ export class BookingHandler
const old_data = event.data.old; const old_data = event.data.old;
const data = event.data.data; const data = event.data.data;
if (data.payment_type != TransactionPaymentType.COUNTER) return;
const booking = await this.bookingService.getOneByOptions({
where: {
id: data.id,
},
relations: ['items'],
});
mappingTransaction(booking);
if ( if (
old_data?.status != data.status && data.payment_type == TransactionPaymentType.COUNTER ||
[STATUS.PENDING, STATUS.ACTIVE].includes(data.status) ([STATUS.ACTIVE, STATUS.SETTLED].includes(data.status) &&
data.payment_type != TransactionPaymentType.COUNTER)
) { ) {
await this.couchService.createDoc( const booking = await this.bookingService.getOneByOptions({
{ where: {
_id: booking.id, id: data.id,
...booking,
}, },
'booking', relations: ['items'],
); });
} else {
await this.couchService.updateDoc( mappingTransaction(booking);
{
_id: booking.id, if (
...booking, (old_data?.status != data.status ||
}, data.payment_type != TransactionPaymentType.COUNTER) &&
'booking', [STATUS.PENDING, STATUS.ACTIVE, STATUS.SETTLED].includes(data.status)
); ) {
await this.couchService.createDoc(
{
_id: booking.id,
...booking,
},
'booking',
);
} else {
await this.couchService.updateDoc(
{
_id: booking.id,
...booking,
},
'booking',
);
}
} }
} }
} }

View File

@ -5,6 +5,9 @@ import { ItemDeletedEvent } from 'src/modules/item-related/item/domain/entities/
import { ItemUpdatedEvent } from 'src/modules/item-related/item/domain/entities/event/item-updated.event'; import { ItemUpdatedEvent } from 'src/modules/item-related/item/domain/entities/event/item-updated.event';
import { ItemChangeStatusEvent } from 'src/modules/item-related/item/domain/entities/event/item-change-status.event'; import { ItemChangeStatusEvent } from 'src/modules/item-related/item/domain/entities/event/item-change-status.event';
import { ItemDataService } from 'src/modules/item-related/item/data/services/item-data.service'; import { ItemDataService } from 'src/modules/item-related/item/data/services/item-data.service';
import { SeasonPeriodUpdatedEvent } from 'src/modules/season-related/season-period/domain/entities/event/season-period-updated.event';
import { SeasonPeriodChangeStatusEvent } from 'src/modules/season-related/season-period/domain/entities/event/season-period-change-status.event';
import { ItemRateUpdatedEvent } from 'src/modules/item-related/item-rate/domain/entities/event/item-rate-updated.event';
@EventsHandler(ItemDeletedEvent) @EventsHandler(ItemDeletedEvent)
export class ItemDeletedHandler implements IEventHandler<ItemDeletedEvent> { export class ItemDeletedHandler implements IEventHandler<ItemDeletedEvent> {
@ -79,3 +82,85 @@ export class ItemUpdatedHandler
} }
} }
} }
@EventsHandler(SeasonPeriodChangeStatusEvent, SeasonPeriodUpdatedEvent)
export class ItemPriceUpdatedHandler
implements IEventHandler<SeasonPeriodChangeStatusEvent>
{
constructor(
private couchService: CouchService,
private itemService: ItemDataService,
) {}
async handle(event: SeasonPeriodChangeStatusEvent) {
const data = event.data.data;
// change status to active
if (data.status == STATUS.ACTIVE) {
const dataItems = await this.itemService.getManyByOptions({
where: {
status: STATUS.ACTIVE,
},
relations: [
'item_category',
'bundling_items',
'bundling_items.item_category',
'item_rates',
'item_rates.item',
'item_rates.season_period',
'item_rates.season_period.season_type',
],
});
for (const dataItem of dataItems) {
await this.couchService.updateDoc(
{
_id: dataItem.id,
...dataItem,
},
'item',
);
}
}
}
}
@EventsHandler(ItemRateUpdatedEvent)
export class ItemRateUpdatedHandler
implements IEventHandler<ItemRateUpdatedEvent>
{
constructor(
private couchService: CouchService,
private itemService: ItemDataService,
) {}
async handle(event: ItemRateUpdatedEvent) {
const data = event.data.data;
const dataItems = await this.itemService.getManyByOptions({
where: {
status: STATUS.ACTIVE,
id: data.item?.id,
},
relations: [
'item_category',
'bundling_items',
'bundling_items.item_category',
'item_rates',
'item_rates.item',
'item_rates.season_period',
'item_rates.season_period.season_type',
],
});
for (const dataItem of dataItems) {
await this.couchService.updateDoc(
{
_id: dataItem.id,
...dataItem,
},
'item',
);
}
}
}

View File

@ -5,6 +5,7 @@ import { UserDeletedEvent } from 'src/modules/user-related/user/domain/entities/
import { UserChangeStatusEvent } from 'src/modules/user-related/user/domain/entities/event/user-change-status.event'; import { UserChangeStatusEvent } from 'src/modules/user-related/user/domain/entities/event/user-change-status.event';
import { UserUpdatedEvent } from 'src/modules/user-related/user/domain/entities/event/user-updated.event'; import { UserUpdatedEvent } from 'src/modules/user-related/user/domain/entities/event/user-updated.event';
import { UserDataService } from 'src/modules/user-related/user/data/services/user-data.service'; import { UserDataService } from 'src/modules/user-related/user/data/services/user-data.service';
import { UserPrivilegeConfigUpdatedEvent } from 'src/modules/user-related/user-privilege/domain/entities/event/user-privilege-configuration-updated.event';
@EventsHandler(UserDeletedEvent) @EventsHandler(UserDeletedEvent)
export class UserDeletedHandler implements IEventHandler<UserDeletedEvent> { export class UserDeletedHandler implements IEventHandler<UserDeletedEvent> {
@ -44,14 +45,16 @@ export class UserUpdatedHandler
], ],
}) })
.then((item) => { .then((item) => {
const user_privilege_configurations = item[ if (item.role != 'superadmin') {
'user_privilege' const user_privilege_configurations = item[
]?.user_privilege_configurations?.filter( 'user_privilege'
(config) => config.module == 'POS', ]?.user_privilege_configurations?.filter(
); (config) => config.module == 'POS',
Object.assign(item['user_privilege'], { );
user_privilege_configurations: user_privilege_configurations, Object.assign(item['user_privilege'], {
}); user_privilege_configurations: user_privilege_configurations,
});
}
return item; return item;
}); });
@ -86,3 +89,52 @@ export class UserUpdatedHandler
} }
} }
} }
@EventsHandler(UserPrivilegeConfigUpdatedEvent)
export class UserPrivilegeUpdateHandler
implements IEventHandler<UserPrivilegeConfigUpdatedEvent>
{
constructor(
private couchService: CouchService,
private userService: UserDataService,
) {}
async handle(event: UserPrivilegeConfigUpdatedEvent) {
const data = event.data.data;
const users = await this.userService
.getManyByOptions({
where: {
user_privilege_id: data.user_privilege_id ?? data.id,
status: STATUS.ACTIVE,
},
relations: [
'user_privilege',
'user_privilege.user_privilege_configurations',
],
})
.then((items) => {
return items?.map((item) => {
const user_privilege_configurations = item[
'user_privilege'
]?.user_privilege_configurations?.filter(
(config) => config.module == 'POS',
);
Object.assign(item['user_privilege'], {
user_privilege_configurations: user_privilege_configurations,
});
return item;
});
});
for (const user of users) {
await this.couchService.updateDoc(
{
_id: user.id,
...user,
},
'user',
);
}
}
}

View File

@ -0,0 +1,22 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { CouchService } from '../../data/services/couch.service';
import { VipCodeCreatedEvent } from 'src/modules/transaction/vip-code/domain/entities/event/vip-code-created.event';
@EventsHandler(VipCodeCreatedEvent)
export class VipCodeCreatedHandler
implements IEventHandler<VipCodeCreatedEvent>
{
constructor(private couchService: CouchService) {}
async handle(event: VipCodeCreatedEvent) {
const data = event.data.data;
await this.couchService.createDoc(
{
_id: data.id,
...data,
},
'vip_code',
);
}
}

View File

@ -1,38 +1,44 @@
import { Body, Controller, Get, Post } from '@nestjs/common'; import { Body, Controller, Get, Injectable, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { Unprotected } from 'src/core/guards'; import { Public } from 'src/core/guards';
import * as Nano from 'nano'; import * as Nano from 'nano';
import { CreateUserPrivilegeDto } from 'src/modules/user-related/user-privilege/infrastructure/dto/create-user-privilege.dto'; import { CreateUserPrivilegeDto } from 'src/modules/user-related/user-privilege/infrastructure/dto/create-user-privilege.dto';
import { ConfigService } from '@nestjs/config';
@ApiTags(`couch`) @ApiTags(`couch`)
@Controller('v1/couch') @Controller('v1/couch')
@Unprotected() @Public()
@Injectable()
export class CouchDataController { export class CouchDataController {
constructor(private configService: ConfigService) {}
get nanoInstance() {
const couchConfiguration = this.configService.get<string>('COUCHDB_CONFIG');
return Nano(couchConfiguration);
}
@Post() @Post()
async createDoc(@Body() entity: CreateUserPrivilegeDto) { async createDoc(@Body() entity: CreateUserPrivilegeDto) {
try { try {
let n = Nano('http://admin:secret@127.0.0.1:5984'); const n = this.nanoInstance;
let db = await n.db.create(entity.name); await n.db.create(entity.name);
} catch (error) { } catch (error) {}
console.log(error, 'dsa');
}
} }
@Post('doc') @Post('doc')
async createDocs(@Body() entity: CreateUserPrivilegeDto) { async createDocs(@Body() entity: CreateUserPrivilegeDto) {
try { try {
const nano = require('nano')('http://admin:secret@127.0.0.1:5984'); const nano = this.nanoInstance;
const people = nano.db.use('string'); const people = nano.db.use('string');
console.log(await people.info()); // const data = {
const data = { // id: '1212',
id: '1212', // name: 'dsadas',
name: 'dsadas', // };
};
// await people.insert(data) // await people.insert(data)
people.changesReader people.changesReader
.start() .start({})
.on('change', (change) => { .on('change', (change) => {
console.log(change); console.log(change);
}) })
@ -45,20 +51,17 @@ export class CouchDataController {
.on('error', (e) => { .on('error', (e) => {
console.error('error', e); console.error('error', e);
}); });
} catch (error) { } catch (error) {}
console.log(error, 'dsa');
}
} }
@Get() @Get()
async getDoc() { async getDoc() {
try { try {
let n = Nano('http://admin:secret@127.0.0.1:5984'); const n = this.nanoInstance;
const people = n.use('string'); const people = n.db.get('user');
return people;
// return people.get(); // return people.get();
} catch (error) { } catch (error) {}
console.log(error, 'dsa');
}
} }
} }

View File

@ -1,3 +1,3 @@
export class CronMidnightEvent { export class CronMidnightEvent {
constructor(public readonly data: {}) {} // constructor(public readonly data: {}) {}
} }

View File

@ -16,6 +16,6 @@ export class MidnightCronManager {
console.log('Cron Event executed every 00:00 minutes.', now); console.log('Cron Event executed every 00:00 minutes.', now);
this.eventBus.publishAll([new CronMidnightEvent({})]); this.eventBus.publishAll([new CronMidnightEvent()]);
} }
} }

View File

@ -0,0 +1,10 @@
export enum InvoiceType {
BOOKING_INVOICE = 'this is your invoice',
PAYMENT_CONFIRMATION = 'payment confirmation',
INVOICE_EXPIRED = 'invoice has expired',
REFUND_REQUEST = 'your refund request',
REFUND_CONFIRMATION = 'refund confirmation',
BOOKING_DATE_CHANGE = 'booking date change',
}
export const PhoneNumber = '088';

View File

@ -0,0 +1,55 @@
import { Injectable } from '@nestjs/common';
import { BaseCustomManager } from 'src/core/modules/domain/usecase/managers/base-custom.manager';
import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity';
import { EventTopics } from 'src/core/strings/constants/interface.constants';
import { STATUS } from 'src/core/strings/constants/base.constants';
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
import { GeneratePdf } from '../templates/helpers/generate-pdf.helper';
@Injectable()
export class PdfMakeManager extends BaseCustomManager<TransactionEntity> {
get entityTarget(): any {
return TransactionModel;
}
get eventTopics(): EventTopics[] {
return [];
}
async validateProcess(): Promise<void> {
return;
}
async beforeProcess(): Promise<void> {
return;
}
async process(): Promise<void> {
try {
const transaction = await this.dataService.getOneByOptions({
where: {
id: this.data.id,
},
relations: ['items'],
});
const banks = await this.dataServiceFirstOpt.getManyByOptions({
where: {
status: STATUS.ACTIVE,
},
});
this.result = GeneratePdf(transaction, this.data.invoice_type, banks);
} catch (error) {
console.log(error, 'generate pdf');
}
return;
}
async afterProcess(): Promise<void> {
return;
}
getResult() {
return this.result;
}
}

View File

@ -0,0 +1,43 @@
import { InvoiceTempalte } from '../invoice.template';
const PdfPrinter = require('pdfmake');
const { PassThrough } = require('stream');
export async function GeneratePdf(transaction, invoiceType, banks) {
var fonts = {
Roboto: {
normal: './fonts/Roboto-Regular.ttf',
bold: './fonts/Roboto-Medium.ttf',
italics: './fonts/Roboto-Italic.ttf',
bolditalics: './fonts/Roboto-MediumItalic.ttf',
},
};
const printer = new PdfPrinter(fonts);
const docDefinition = InvoiceTempalte(transaction, invoiceType, banks);
const createPdfBuffer = (docDefinition) => {
return new Promise((resolve, reject) => {
const pdfDoc = printer.createPdfKitDocument(docDefinition);
const chunks = [];
const stream = new PassThrough();
pdfDoc.pipe(stream);
pdfDoc.end();
stream.on('data', (chunk) => {
chunks.push(chunk);
});
stream.on('end', () => {
const pdfBuffer = Buffer.concat(chunks);
resolve(pdfBuffer);
});
stream.on('error', reject);
});
};
const pdfBuffer = await createPdfBuffer(docDefinition);
return pdfBuffer;
}

View File

@ -0,0 +1,443 @@
import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity';
import { InvoiceType, PhoneNumber } from '../../../constants';
import { PaymentMethodEntity } from 'src/modules/transaction/payment-method/domain/entities/payment-method.entity';
export function mappingHeader(transaction: TransactionEntity, invoiceType) {
return [
{
stack: [
{
alignment: 'center',
columns: [
{
width: 100,
image: 'data',
},
{
width: 'auto',
text: 'have',
fontSize: 50,
bold: true,
color: '#169f54',
padding: [0, 0, 0, 0],
margin: [0, 0, 0, 0],
alignment: 'center',
},
{
width: 'auto',
text: 'fun',
fontSize: 50,
bold: true,
color: '#61c4eb',
padding: [0, 0, 0, 0],
margin: [0, 0, 0, 0],
// alignment: "center"
},
],
},
{
text: invoiceType.toUpperCase(),
fontSize: 30,
alignment: 'center',
},
{
columns: [
{
text: transaction.invoice_code,
},
{
text: new Date(transaction.booking_date).toDateString(),
alignment: 'right',
},
],
},
],
},
{
width: 150,
text: 'Jl, Kolonel Masturi No.KM. 11, \n Kertawangi, Kec. Cisatua, \n Kab. Bandung Barat, \n Jawa Barat 40551 \n 0815-6380-8021',
// color: '#aaaaab',
// bold: true,
fontSize: 11,
margin: [0, 20, 0, 5],
},
];
}
export function mappingFooter() {
return [
[
{
text: 'we commits to prividing an educative, \n playful, and purposeful environment\n this is advantageous for all ages',
border: [false, true, false, false],
margin: [0, 5, 0, 5],
alignment: 'right',
},
{
text: 'Thank \n You',
border: [false, true, false, false],
fontSize: 20,
bold: true,
color: '#169f54',
margin: [0, 5, 0, 5],
},
],
];
}
export function mappingPrice(
transaction: TransactionEntity,
invoiceType: InvoiceType,
) {
const result = [];
const totalData = [
InvoiceType.REFUND_CONFIRMATION,
InvoiceType.REFUND_REQUEST,
].includes(invoiceType)
? transaction['refund'].refund_total
: Number(transaction.payment_total).toLocaleString('id-ID', {
style: 'currency',
currency: 'IDR',
});
const subTotalData = [
InvoiceType.REFUND_CONFIRMATION,
InvoiceType.REFUND_REQUEST,
].includes(invoiceType)
? transaction['refund'].refund_total
: Number(transaction.payment_sub_total).toLocaleString('id-ID', {
style: 'currency',
currency: 'IDR',
});
const sub_total = [
{
text: 'SUBTOTAL',
alignment: 'right',
bold: true,
margin: [0, 5, 0, 5],
},
{
text: subTotalData,
margin: [0, 5, 0, 5],
},
];
result.push(sub_total);
if (Number(transaction.payment_discount_total ?? 0) > 0) {
const discount = [
{
text: 'DISCOUNT',
bold: true,
alignment: 'right',
margin: [0, 5, 0, 5],
},
{
text: Number(transaction.payment_discount_total).toLocaleString(
'id-ID',
{
style: 'currency',
currency: 'IDR',
},
),
margin: [0, 5, 0, 5],
},
];
result.push(discount);
}
const total = [
{
text: 'TOTAL',
bold: true,
border: [false, false, false, true],
alignment: 'right',
margin: [0, 5, 0, 5],
},
{
text: totalData,
border: [false, false, false, true],
margin: [0, 5, 0, 5],
},
];
result.push(total);
return result;
}
export function mappingItem(transaction, invoiceType: InvoiceType) {
const header = [
{
text: 'ITEM',
border: [false, true, false, false],
margin: [0, 5, 0, 5],
bold: true,
textTransform: 'uppercase',
},
{
text: 'QTY',
alignment: 'center',
border: [false, true, false, false],
margin: [0, 5, 0, 5],
bold: true,
textTransform: 'uppercase',
},
{
text: 'PRICE',
alignment: 'center',
border: [false, true, false, false],
margin: [0, 5, 0, 5],
bold: true,
textTransform: 'uppercase',
},
{
text: 'AMOUNT',
border: [false, true, false, false],
alignment: 'center',
bold: true,
margin: [0, 5, 0, 5],
textTransform: 'uppercase',
},
];
const result = [];
if (
[InvoiceType.REFUND_CONFIRMATION, InvoiceType.REFUND_REQUEST].includes(
invoiceType,
)
) {
transaction.refund?.refund_items
?.filter((item) => Number(item.qty_refund) > 0)
.forEach((item) => {
const dataRow = [
{
text: item.transaction_item.item_name,
margin: [0, 5, 0, 5],
alignment: 'left',
},
{
text: item.qty_refund,
margin: [0, 5, 0, 5],
alignment: 'center',
},
{
text: Number(item.transaction_item.total_price).toLocaleString(
'id-ID',
{
style: 'currency',
currency: 'IDR',
},
),
margin: [0, 5, 0, 5],
alignment: 'right',
},
{
text: Number(item.refund_total).toLocaleString('id-ID', {
style: 'currency',
currency: 'IDR',
}),
alignment: 'right',
margin: [0, 5, 0, 5],
},
];
result.push(dataRow);
});
} else {
transaction.items.forEach((item) => {
const dataRow = [
{
text: item.item_name,
margin: [0, 5, 0, 5],
alignment: 'left',
},
{
text: item.qty,
margin: [0, 5, 0, 5],
alignment: 'center',
},
{
text: Number(item.item_price).toLocaleString('id-ID', {
style: 'currency',
currency: 'IDR',
}),
margin: [0, 5, 0, 5],
alignment: 'right',
},
{
text: Number(item.total_price).toLocaleString('id-ID', {
style: 'currency',
currency: 'IDR',
}),
alignment: 'right',
margin: [0, 5, 0, 5],
},
];
result.push(dataRow);
});
}
const body = [header, ...result];
return body;
}
export function mappingBody(
transaction: TransactionEntity,
invoiceType: InvoiceType,
) {
// booking date change information
if (invoiceType == InvoiceType.BOOKING_DATE_CHANGE) {
return [
"Great news! We've successfully updated your booking date as per your request. \n We're exited to accommodate your new plans and ensure everything goes smoothly \n\n",
'Here are your updated booking details:',
{
text: `\n\n Original Booking Date: ${new Date(
transaction['booking_date_before'],
).toDateString()} \n New Booking Date: ${new Date(
transaction.booking_date,
).toDateString()} \n\n`,
bold: true,
},
"Here's a quick recap of your order :",
];
}
// booking invoice
else if (invoiceType == InvoiceType.BOOKING_INVOICE) {
return [
"Thank you for choosing us! We're absolutely thrilled and can't wait to embark on this exiting day with you. See you soon for fun times ahead!",
];
} else if (invoiceType == InvoiceType.PAYMENT_CONFIRMATION) {
// booking payment confirmation
return [
'We are exited to inform you that your payment has been successfully received! \n',
'Attached to this email, you will find your confirmation receipt. \n',
'Please keep this safe as you will need to show it at the entrance upon your arrival. \n',
"It's your golden ticket to all the fun and excitement awaiting you \n\n",
"Here's a quick recap: \n",
];
}
// expired information invoice
// else if (invoiceType == InvoiceType.INVOICE_EXPIRED) {
// return [
// "We hope this message finds you well!",
// "Uh-oh! it looks like your invoice, dated 15 Juli, has officially expired as of 15 Juli. But no worries, we can fix this together \n",
// "To keep the goof times rolling, our friendly support team is just a call away at \n",
// "0564645 \n\n",
// "Here are the detail of the expired invoice: "
// ]
// }
// refund information
else if (invoiceType == InvoiceType.REFUND_REQUEST) {
return [
"We'ew trully sorry for any inconvenience that led to this request. \n",
"We've received your refund request for: \n",
];
}
// refund confirmation
else if (invoiceType == InvoiceType.REFUND_CONFIRMATION) {
return [
'Good news! \n',
"We've successfully processed your refund for: \n",
];
}
}
export function mappingBodyBottom(
transaction: TransactionEntity,
invoiceType: InvoiceType,
banks: PaymentMethodEntity[],
) {
if (invoiceType == InvoiceType.BOOKING_DATE_CHANGE) {
// booking date change information
return [
"For your convenience, we've attached a new confirmation receipt reflecting these changes \n",
'Please be sure to bring this updated receipt with you on the new date \n\n',
'If you have any questions or need further assistance, our friendly support team is just a call away at \n\n',
PhoneNumber,
"\nThank you and we can't wait to see you and make sure you hove an amazing time!",
];
} else if (invoiceType == InvoiceType.BOOKING_INVOICE) {
// booking invoice
return [
'Just a friendly reminder that your invoice will expire on 24 Agustus 2024 \n',
'To keep things running smoothly, please ensure your payment is completed before this data. \n',
'\nFor youe convenience, here is a list of our account details \n\n',
{
text: [
banks.forEach((bank) => {
return {
text: `${bank.issuer_name} ${bank.account_number} a/n ${bank.account_name} \n`,
bold: true,
};
}),
],
},
"\n Once you've made the payment, please kindly email or send the proof of payment so we can proceed with your booking promptly\n",
'If you have any questions or need assistance, feel free to reach out to our support team at\n',
PhoneNumber,
];
}
// booking payment confirmation
else if (invoiceType == InvoiceType.PAYMENT_CONFIRMATION) {
return [
'If you have any questions or need assistance, feel free to reach out to our support team at\n',
PhoneNumber,
"\nDon't forget to bring a smile and your confirmation receipt (attached) for a smooth entry. \n",
"We can't wait to see you and ensure you have an amazing time with us!",
];
}
// expired information invoice
else if (invoiceType == InvoiceType.INVOICE_EXPIRED) {
return [];
}
// refund information
else if (invoiceType == InvoiceType.REFUND_REQUEST) {
return [
"Your satisfaction is important to us, and we're commited to resolving this as quickly as possible.\n",
'Our team is already on it and will process your refund request promptly. \n',
"We'll keep you updated and notify you once the refund has been processed. \n",
"If you have any questions or need futher assistance, don't hestitate to reach out us at \n",
PhoneNumber,
'\n\n',
'Thank you for your patience and understanding \n',
'We appreciate your feedback and here to make things right!',
];
}
// refund confirmation
else if (invoiceType == InvoiceType.REFUND_CONFIRMATION) {
return [
'Here are the details of your refund: \n\n',
{
text: `Transaction Number: ${transaction.invoice_code} \n`,
},
{
text: `Refund Processed: ${transaction['refund'].refund_date}\n`,
},
{
text: `Bank Account: ${transaction['refund'].bank_name} \n`,
},
{
text: `Account Number: ${transaction['refund'].bank_account_number} \n`,
},
{
text: `Account Name: ${transaction['refund'].bank_account_name} \n`,
},
"\n We hope this helps make things righ, and we're he to assist if you need anything else. \n",
'You should see the refund reflected in your account within 3 Business days \n\n',
'Thank you for your patience and understanding\n',
'If you have any questions or need assistance, feel free to reach out to our support team at \n',
PhoneNumber,
"\nWe're alyways here to help!",
];
}
}

View File

@ -0,0 +1,215 @@
import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity';
import {
mappingBody,
mappingBodyBottom,
mappingFooter,
mappingHeader,
mappingItem,
mappingPrice,
} from './helpers/invoice-mapping.helper';
import { InvoiceType } from '../../constants';
import { PaymentMethodEntity } from 'src/modules/transaction/payment-method/domain/entities/payment-method.entity';
import * as fs from 'fs';
export function InvoiceTempalte(
transaction: TransactionEntity,
invoiceType: InvoiceType,
banks: PaymentMethodEntity[],
) {
const filePath = './image/logo.jpeg';
const imageBase64 = fs.readFileSync(filePath).toString('base64');
const imageUrl = `data:image/png;base64,${imageBase64}`;
return {
content: [
{
alignment: 'justify',
columns: mappingHeader(transaction, invoiceType),
},
'\n\n',
// tipe booking date change tidak ada
{
columns: [
{
text: `Dear, \n ${transaction.customer_name} \n ${
transaction.customer_phone
} \n Booking Date: ${new Date(
transaction.booking_date,
).toDateString()}`,
bold: true,
},
],
},
'\n',
{
text: mappingBody(transaction, invoiceType),
},
'\n',
{
layout: {
defaultBorder: false,
hLineWidth: function (i, node) {
return 1;
},
vLineWidth: function (i, node) {
return 1;
},
hLineColor: function (i, node) {
return i === 0 ? '#000000' : '#eaeaea';
},
vLineColor: function (i, node) {
return '#eaeaea';
},
hLineStyle: function (i, node) {
// if (i === 0 || i === node.table.body.length) {
return null;
//}
},
// vLineStyle: function (i, node) { return {dash: { length: 10, space: 4 }}; },
paddingLeft: function (i, node) {
return 10;
},
paddingRight: function (i, node) {
return 10;
},
paddingTop: function (i, node) {
return 3;
},
paddingBottom: function (i, node) {
return 3;
},
fillColor: function (rowIndex, node, columnIndex) {
return '#fff';
},
},
table: {
widths: ['*', 'auto', 'auto', 100],
body: mappingItem(transaction, invoiceType),
},
},
'\n',
{
layout: {
defaultBorder: false,
hLineWidth: function (i, node) {
return 1;
},
vLineWidth: function (i, node) {
return 1;
},
hLineColor: function (i, node) {
return i === 3 ? '#000000' : '#eaeaea';
},
vLineColor: function (i, node) {
return '#eaeaea';
},
hLineStyle: function (i, node) {
// if (i === 0 || i === node.table.body.length) {
return null;
//}
},
// vLineStyle: function (i, node) { return {dash: { length: 10, space: 4 }}; },
paddingLeft: function (i, node) {
return 10;
},
paddingRight: function (i, node) {
return 10;
},
paddingTop: function (i, node) {
return 3;
},
paddingBottom: function (i, node) {
return i === 2 ? 20 : 3;
},
fillColor: function (rowIndex, node, columnIndex) {
return '#fff';
},
},
table: {
headerRows: 1,
widths: ['*', 100],
body: mappingPrice(transaction, invoiceType),
},
},
'\n',
{
text: mappingBodyBottom(transaction, invoiceType, banks),
},
'\n',
{
layout: {
defaultBorder: false,
hLineWidth: function (i, node) {
return 1;
},
vLineWidth: function (i, node) {
return 1;
},
hLineColor: function (i, node) {
return i === 0 ? '#000000' : '#eaeaea';
},
vLineColor: function (i, node) {
return '#eaeaea';
},
hLineStyle: function (i, node) {
// if (i === 0 || i === node.table.body.length) {
return null;
//}
},
// vLineStyle: function (i, node) { return {dash: { length: 10, space: 4 }}; },
paddingLeft: function (i, node) {
return 10;
},
paddingRight: function (i, node) {
return 10;
},
paddingTop: function (i, node) {
return 20;
},
paddingBottom: function (i, node) {
return 3;
},
fillColor: function (rowIndex, node, columnIndex) {
return '#fff';
},
},
table: {
widths: ['*', 200],
body: mappingFooter(),
},
},
],
styles: {
notesTitle: {
fontSize: 10,
bold: true,
margin: [0, 50, 0, 3],
},
notesText: {
fontSize: 10,
},
tableExample: {
margin: [0, 5, 0, 15],
headerRows: 1,
widths: ['*', 100],
},
tableHeader: {
bold: true,
fontSize: 13,
color: 'black',
},
},
defaultStyle: {
columnGap: 20,
},
images: {
data: imageUrl,
},
};
}

View File

@ -0,0 +1,23 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { PdfMakeManager } from './domain/managers/pdf-make.manager';
import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service';
import { PaymentMethodDataService } from 'src/modules/transaction/payment-method/data/services/payment-method-data.service';
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model';
import { PaymentMethodModel } from 'src/modules/transaction/payment-method/data/models/payment-method.model';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
import { CqrsModule } from '@nestjs/cqrs';
import { TransactionTaxModel } from 'src/modules/transaction/transaction/data/models/transaction-tax.model';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forFeature([TransactionModel], CONNECTION_NAME.DEFAULT),
CqrsModule,
],
controllers: [],
providers: [PdfMakeManager],
})
export class ExportModule {}

View File

@ -0,0 +1,16 @@
import { Controller, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Public } from 'src/core/guards';
@ApiTags('export')
@Controller('export')
@Public(true)
export class ExportController {
constructor() {}
// @Post('pdf/example')
// async exportPdf(
// ): Promise<any> {
// return PdfMaker();
// }
}

View File

@ -0,0 +1,82 @@
import { google } from 'googleapis';
import * as fs from 'fs';
import * as path from 'path';
import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity';
export async function CreateEventCalendarHelper(
transaction: TransactionEntity,
isDelete = false,
) {
let result;
const filePath = path.join(
__dirname,
'../../../../../../../../',
'google-credential.json',
);
const credential = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const client = new google.auth.JWT({
email: credential.client_email,
key: credential.private_key,
scopes: ['https://www.googleapis.com/auth/calendar'],
});
const calendar = google.calendar({
version: 'v3',
auth: client,
});
const eventData = mappingData(transaction);
if (transaction.calendar_id) {
result = await calendar.events.update(
{
calendarId: process.env.GOOGLE_CALENDAR_ID,
eventId: transaction.calendar_id,
requestBody: eventData,
},
{},
);
} else if (!isDelete) {
result = await calendar.events.insert(
{
calendarId: process.env.GOOGLE_CALENDAR_ID,
requestBody: eventData,
},
{},
);
} else {
result = await calendar.events.delete(
{
calendarId: process.env.GOOGLE_CALENDAR_ID,
eventId: transaction.calendar_id,
},
{},
);
}
return result?.data;
}
function mappingData(transaction) {
return {
summary: transaction.customer_name ?? transaction.invoice_code,
description: `<b>Booking for invoice ${
transaction.invoice_code
}</b><p>List Items :</p><ul>${transaction.items.map(
(item) => `<li>${item.item_name}</li>`,
)}</ul>`,
start: {
dateTime: new Date(transaction.booking_date).toISOString(),
timeZone: 'Asia/Jakarta',
},
end: {
dateTime: new Date(transaction.booking_date).toISOString(),
timeZone: 'Asia/Jakarta',
},
reminders: {
useDefault: false,
},
};
}

View File

@ -8,7 +8,7 @@ export class IndexHolidayCalendarManager {
const events = []; const events = [];
const calendar = google.calendar({ const calendar = google.calendar({
version: 'v3', version: 'v3',
auth: 'AIzaSyCsCt6PDd6uYLkahvtdvCoMWf-1_QaLiNM', auth: process.env.GOOGLE_CALENDAR_KEY,
}); });
const calendarId = 'id.indonesian#holiday@group.v.calendar.google.com'; const calendarId = 'id.indonesian#holiday@group.v.calendar.google.com';

View File

@ -4,10 +4,29 @@ import { CqrsModule } from '@nestjs/cqrs';
import { IndexHolidayCalendarManager } from '../../configuration/google-calendar/domain/usecases/managers/index-holiday-google-calendar.manager'; import { IndexHolidayCalendarManager } from '../../configuration/google-calendar/domain/usecases/managers/index-holiday-google-calendar.manager';
import { GoogleCalendarController } from './infrastructure/google-calendar.controller'; import { GoogleCalendarController } from './infrastructure/google-calendar.controller';
import { GoogleCalendarOrchestrator } from './domain/usecases/google-calendar.orchestrator'; import { GoogleCalendarOrchestrator } from './domain/usecases/google-calendar.orchestrator';
import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service';
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model';
import { TransactionTaxModel } from 'src/modules/transaction/transaction/data/models/transaction-tax.model';
@Module({ @Module({
imports: [ConfigModule.forRoot(), CqrsModule], imports: [
ConfigModule.forRoot(),
TypeOrmModule.forFeature(
[TransactionModel, TransactionItemModel, TransactionTaxModel],
CONNECTION_NAME.DEFAULT,
),
CqrsModule,
],
controllers: [GoogleCalendarController], controllers: [GoogleCalendarController],
providers: [IndexHolidayCalendarManager, GoogleCalendarOrchestrator], providers: [
IndexHolidayCalendarManager,
TransactionDataService,
GoogleCalendarOrchestrator,
],
}) })
export class GoogleCalendarModule {} export class GoogleCalendarModule {}

View File

@ -1,5 +1,5 @@
import { GoogleCalendarOrchestrator } from './../domain/usecases/google-calendar.orchestrator'; import { GoogleCalendarOrchestrator } from './../domain/usecases/google-calendar.orchestrator';
import { Controller, Get, Query } from '@nestjs/common'; import { Controller, Get, Post, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { Public } from 'src/core/guards'; import { Public } from 'src/core/guards';
import { FilterGoogleCalendarDto } from './dto/filter-google-calendar.dto'; import { FilterGoogleCalendarDto } from './dto/filter-google-calendar.dto';

Some files were not shown because too many files have changed in this diff Show More