Compare commits

...

84 Commits

Author SHA1 Message Date
6f9bdff115 update
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m59s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 18s
Build, Push and Deploy / deploy-staging (push) Successful in 39s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-14 12:25:21 +07:00
ce2b815b07 Fix BadMethodCallException and remaining PostgreSQL issues 2026-05-14 12:24:33 +07:00
b76d34cc64 update
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 4m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 39s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-14 12:12:26 +07:00
05fd3230b8 update marketing
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 5m14s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-14 11:55:22 +07:00
f80fcc4c1b cari error git
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 4m22s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 42s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-12 08:28:50 +07:00
b61a076fa6 cek log error
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 4m40s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 42s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-11 11:16:47 +07:00
8a567280ae update perbaikan email
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m51s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 38s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-09 15:24:19 +07:00
145bd5675f update mail
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m48s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 39s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-09 15:09:09 +07:00
6e076e8f55 update mail flow
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 4m32s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-09 14:50:35 +07:00
0cb58d3419 update error
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 4m50s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-06 09:49:01 +07:00
28510f1163 update docker ignore
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m47s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 38s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-05 18:07:28 +07:00
f301d311d6 update date
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m33s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 33s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-05 17:54:11 +07:00
353eec5e74 update git ignore
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m29s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 35s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-05 17:42:43 +07:00
e49654a1f7 update compose
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m30s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 35s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-05 17:33:22 +07:00
3b3a1da5c3 update migration
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m27s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 23s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-05 17:18:42 +07:00
30de18d283 update big migrate
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 4m17s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 20s
Build, Push and Deploy / deploy-staging (push) Successful in 35s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-05 15:29:32 +07:00
e34027132e update
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m50s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 33s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-04 23:30:59 +07:00
1dde763a73 solving error
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m55s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 40s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-04 23:13:25 +07:00
3e1b64e008 update addon HRM
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 3m30s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-05-04 23:04:09 +07:00
7be161f4e4 resolving
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 5m14s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-27 08:58:08 +07:00
7beac673c8 pull from web 2026-04-27 08:56:13 +07:00
triagungbiantoro
417b7b7453 harga pada beranda terhubung ke manage plans di dashboard admin
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m27s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 31s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-25 21:57:25 +07:00
f25542ea0d update grafik revenuw di dashboard
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m58s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 42s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-23 22:28:02 +07:00
f2cd16a2a8 update querry report profit n lost
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m48s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 40s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-23 22:17:41 +07:00
4f530ff301 perbaikan product string 1 bugs
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m51s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 23:08:39 +07:00
6319d4c6cb update on psosale string 1 bugs
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m15s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 36s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 22:47:24 +07:00
2173c3ee81 update gitignore composer.js
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m23s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 21:41:31 +07:00
dcaf267458 update lock clucknut
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / build-and-push (push) Successful in 3m14s
Build, Push and Deploy / deploy-staging (push) Successful in 25s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 20:32:18 +07:00
4554035227 fix: enforce php 8.2.30 platform for docker compatibility
Some checks failed
Build, Push and Deploy / deploy-staging (push) Has been cancelled
Build, Push and Deploy / deploy-production (push) Has been cancelled
Build, Push and Deploy / build-and-push (push) Has been cancelled
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
2026-04-18 20:29:54 +07:00
f459f03d0c perbaikan bug dashboard
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m20s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 26s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 19:55:00 +07:00
ef902b2604 update bug daashboards 2026-04-18 19:47:13 +07:00
dd60899d9e updater
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m29s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 26s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 19:07:27 +07:00
1e252a0e4c update git pus
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m35s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 30s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 16:22:32 +07:00
ed9654271b fix: sync composer.lock with composer.json after adding scribe and missing extensions 2026-04-18 16:21:59 +07:00
1228c52538 update after stop build
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m36s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 42s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 16:10:57 +07:00
e449146306 update dockerfile
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 2m15s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 16:02:16 +07:00
62417c44be Update bunines bugs
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 2m57s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-18 15:50:39 +07:00
e2fa4d2d7b create insert db querry
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m31s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-16 05:04:06 +07:00
75dfca9128 update
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m17s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-15 22:26:07 +07:00
58edd89bd1 refressh database
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 4m1s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 35s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-15 20:34:37 +07:00
de510a05f1 seeder db
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m46s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 18s
Build, Push and Deploy / deploy-staging (push) Successful in 45s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-13 09:24:39 +07:00
4e58905bf7 migrate
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / build-and-push (push) Successful in 3m0s
Build, Push and Deploy / deploy-staging (push) Successful in 36s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-12 23:49:02 +07:00
2e2b0ee178 test migrate 2026-04-12 23:46:56 +07:00
eko
d9988d59a4 fix entrypoint
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 2m56s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 25s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-12 22:38:52 +07:00
eko
afc31bc825 fix entrypoint
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m25s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 29s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-12 22:23:56 +07:00
eko
ac2ec6e659 add swagger
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m28s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 38s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-12 22:06:46 +07:00
eko
75ece668cc fix vald
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m2s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 35s
Build, Push and Deploy / deploy-production (push) Has been skipped
2026-04-05 00:57:34 +07:00
eko
eafa8d362f fix vald
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 36s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-04-05 00:39:10 +07:00
eko
2d2cb95600 fix val
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m0s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 36s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-05 00:18:48 +07:00
eko
1d63c28356 remove route::cache production
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m12s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-04-04 23:51:47 +07:00
eko
4398aee449 fix production
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m9s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 38s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-04 23:34:45 +07:00
eko
481b8fba7e fix pipeline production still use port 8000
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m15s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 39s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-04 23:12:57 +07:00
cdd7fbaecb csrf
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m10s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-03 21:06:42 +07:00
ff60e63ece crsf bugs
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m37s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-03 20:41:20 +07:00
e5d8df803f hapus
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 2m58s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-04-02 23:20:02 +07:00
df323c1c70 gdockerignore cache
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 3m10s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 13s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-04-02 23:12:48 +07:00
c0d1714543 docker ignore cache
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 3m24s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-02 23:05:21 +07:00
2f17c3abdd update pull
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m13s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-04-02 22:00:30 +07:00
ee73c81dde Merge branch 'main' of https://kode.sadateknologi.site/yanto/kulakpos_web 2026-04-02 21:39:22 +07:00
78dd794f71 pulldata 2026-04-02 21:38:46 +07:00
triagungbiantoro
1ab56d68b3 perbaikan tombol e-wallet
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m59s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 38s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-02 21:26:01 +07:00
triagungbiantoro
ac43e83b38 Perbaikan Button Pilih Basic dan Pilih Pro
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m13s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 43s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-02 09:12:29 +07:00
triagungbiantoro
80f4d8f046 perbaikan mobile view + no Whatsapp
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m57s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 38s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-01 18:06:09 +07:00
triagungbiantoro
8fafbccb66 ganti logo dan link tombol Jadwalkan Demo
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m47s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 40s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-04-01 09:19:43 +07:00
f2c19ec025 update git
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m8s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 26s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-31 08:27:42 +07:00
8fb1995913 folder
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 2m38s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 31s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-31 01:32:38 +07:00
d346b24299 update docker file
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 2m0s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-31 01:25:48 +07:00
1c730d154d test second dockeerfile
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 1m55s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-31 01:17:24 +07:00
94a70c95c0 remove composer lock
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 2m47s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 28s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-30 18:07:58 +07:00
a5638095f1 update git
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 2m40s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 15s
Build, Push and Deploy / deploy-staging (push) Successful in 29s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-30 17:50:31 +07:00
b5e3a778ce allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-30 14:54:57 +07:00
66aed7c4e8 update bug docker file
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m7s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 8s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-30 14:32:56 +07:00
327dceee4e update bugs dockerfile
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m27s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 9s
Build, Push and Deploy / deploy-staging (push) Successful in 37s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-30 14:18:41 +07:00
eko
d722295036 fix /plan
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 2m57s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 7s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-29 19:35:21 +07:00
eko
74e6666da5 fix docker
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 8s
Build, Push and Deploy / build-and-push (push) Successful in 2m39s
Build, Push and Deploy / deploy-staging (push) Successful in 22s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-29 15:42:51 +07:00
eko
a234bc497e fix docker
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 1m56s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 8s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-29 15:33:07 +07:00
eko
957352e257 fix docker
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 2m35s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 9s
Build, Push and Deploy / deploy-staging (push) Successful in 21s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-29 15:12:24 +07:00
eko
6b34fcb87a fix docker
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 2m36s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 8s
Build, Push and Deploy / deploy-staging (push) Successful in 30s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-29 14:53:39 +07:00
eko
46b1a4f74d fix docker
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 1m51s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 9s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-29 14:45:23 +07:00
eko
b0a929684a fix dockerfile
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 1m52s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 8s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-29 14:37:23 +07:00
eko
30a3f05cbb fix dockerfile
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 1m49s
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 8s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-29 14:32:03 +07:00
eko
0be65d8013 adapt version
Some checks failed
Build, Push and Deploy / build-and-push (push) Successful in 2m28s
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 8s
Build, Push and Deploy / deploy-staging (push) Successful in 28s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-29 14:11:26 +07:00
eko
bd85604fb4 using vite: ^8.0.3
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 1m40s
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 8s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 0s
2026-03-29 14:01:39 +07:00
eko
f1b383fbc7 add vite
Some checks failed
Build, Push and Deploy / build-and-push (push) Failing after 1m33s
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 8s
Build, Push and Deploy / deploy-staging (push) Has been skipped
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
2026-03-29 13:48:35 +07:00
22597 changed files with 2981628 additions and 6761 deletions

30
.dockerignore Normal file
View File

@@ -0,0 +1,30 @@
# **/node_modules
# **/vendor
# #.env
# .env.backup
# .git
# .phpunit.result.cache
# Homestead.json
# Homestead.yaml
# auth.json
# npm-debug.log
# yarn-error.log
# .idea
# .vscode
# storage/app/public
# storage/app/temp
# storage/app/uploads
# storage/debugbar
# storage/framework/views/*
# public/modules/*
# .qodo
# .camel-jbang
# # Ignore large archives that slow down docker build context
# *.zip
# *.tar.gz
# *.sqlstorage/framework/sessions/*
storage/framework/sessions/*
storage/framework/views/*
storage/framework/cache/*
bootstrap/cache/*

View File

@@ -84,7 +84,7 @@ jobs:
echo "Starting new container..."
docker run -d \
--restart unless-stopped \
--health-cmd="curl -f http://localhost:8000 || exit 1" \
--health-cmd="curl -f http://127.0.0.1:8000 || exit 1" \
--health-interval=30s \
--health-timeout=10s \
--health-retries=3 \
@@ -98,7 +98,7 @@ jobs:
# Check if container is running
sleep 5
if docker ps | grep -q kulakpos_web_staging; then
if docker ps | grep kulakpos_web_staging; then
echo "✅ Staging deployment successful!"
docker logs --tail 20 kulakpos_web_staging
else
@@ -183,7 +183,13 @@ jobs:
docker ps --filter name=kulakpos_web_prod
# Create backup of current deployment info
docker inspect kulakpos_web_prod > /tmp/kulakpos_backup_$(date +%Y%m%d_%H%M%S).json || true
mkdir -p /opt/kulakpos/backups
docker inspect kulakpos_web_prod > /opt/kulakpos/backups/kulakpos_backup_$(date +%Y%m%d_%H%M%S).json || true
# Backup .env file
if [ -f "/opt/kulakpos/.env" ]; then
cp /opt/kulakpos/.env /opt/kulakpos/backups/.env_backup_$(date +%Y%m%d_%H%M%S)
fi
# Pull the specified image
echo "Pulling image: kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:$IMAGE_TAG"
@@ -194,11 +200,11 @@ jobs:
docker stop kulakpos_web_prod || true
docker rm kulakpos_web_prod || true
# Run new container
echo "Starting new container..."
# Run new container (using PHP's built-in server on port 8000 like staging)
echo "Starting new production container on port 8000..."
docker run -d \
--restart unless-stopped \
--health-cmd="pgrep php-fpm" \
--health-cmd="curl -f http://127.0.0.1:8000 || exit 1" \
--health-interval=30s \
--health-timeout=10s \
--health-start-period=40s \
@@ -206,15 +212,23 @@ jobs:
--name kulakpos_web_prod \
--network="host" \
-v /opt/kulakpos/.env:/var/www/html/.env \
-p 9000:9000 \
-e MODE=prod \
-e MODE=production \
-e APP_ENV=production \
-e APP_DEBUG=false \
-e AUTO_MIGRATE=false \
kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:$IMAGE_TAG
# Check if container is running
# Wait for container to be ready
echo "Waiting for container to be ready..."
sleep 10
if docker ps | grep -q kulakpos_web_prod; then
# Check if container is running
if docker ps | grep kulakpos_web_prod; then
echo "✅ Production deployment successful!"
echo ""
echo "Container status:"
docker ps --filter name=kulakpos_web_prod --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "Container logs (last 20 lines):"
docker logs --tail 20 kulakpos_web_prod
else
@@ -222,50 +236,31 @@ jobs:
docker logs kulakpos_web_prod || echo "No logs available"
# Attempt rollback to previous version if available
echo ""
echo "Attempting rollback to previous version..."
PREVIOUS_IMAGE=$(docker inspect kulakpos_web_prod --format='{{.Config.Image}}' 2>/dev/null || echo "")
PREVIOUS_BACKUP=$(ls -t /opt/kulakpos/backups/kulakpos_backup_*.json 2>/dev/null | head -1)
if [ -f "$PREVIOUS_BACKUP" ]; then
PREVIOUS_IMAGE=$(jq -r '.[0].Config.Image' $PREVIOUS_BACKUP 2>/dev/null || echo "")
if [ -n "$PREVIOUS_IMAGE" ] && [ "$PREVIOUS_IMAGE" != "kode.sadateknologi.site/${{ gitea.repository_owner }}/kulakpos_web:$IMAGE_TAG" ]; then
echo "Rolling back to: $PREVIOUS_IMAGE"
docker run -d \
--restart unless-stopped \
--health-cmd="curl -f http://127.0.0.1:8000 || exit 1" \
--health-interval=30s \
--health-timeout=10s \
--health-start-period=40s \
--health-retries=3 \
--name kulakpos_web_prod \
--network="host" \
-v /opt/kulakpos/.env:/var/www/html/.env \
-p 8000:8000 \
-e MODE=prod \
-e MODE=production \
-e APP_ENV=production \
-e APP_DEBUG=false \
-e AUTO_MIGRATE=false \
$PREVIOUS_IMAGE
echo "Rollback attempted"
echo "Rollback completed"
fi
fi
exit 1
fi
EOF
# - name: Verify Production Deployment
# run: |
# ssh kulakpos_prod "curl -f http://localhost:8000/health || curl -f http://localhost:8000 || echo 'Service is running but health check endpoint not configured'"
# echo "✅ Production deployment verified!"
- name: Verify Production Deployment
run: |
ssh kulakpos_prod "docker ps --filter 'name=kulakpos_web_prod' --format '{{.Status}}' | grep -q healthy"
echo "✅ Production deployment verified!"
- name: Send Deployment Notification
if: always()
run: |
STATUS="${{ job.status }}"
if [ "$STATUS" = "success" ]; then
echo "✅ Production deployment completed successfully!"
else
echo "❌ Production deployment failed!"
exit 1
fi
cleanup:
runs-on: ubuntu-latest
needs: [deploy-staging, deploy-production]
if: always()
steps:
- name: Cleanup old Docker images on runners
run: |
docker system prune -f --filter "until=24h"

View File

@@ -25,7 +25,6 @@ jobs:
- run: head -n 5 app/Helpers/Helper.php
- run: ls -la app/Helpers/Helper.php
- run: file app/Helpers/Helper.php
- run: nl -ba app/Helpers/Helper.php | head -10
- run: pwd
- run: whoami

2
.gitignore vendored
View File

@@ -20,3 +20,5 @@ yarn-error.log
/public/modules/*
.qodo
.camel-jbang
dump/
db/

0
.scannerwork/.sonar_lock Normal file
View File

View File

@@ -0,0 +1,6 @@
projectKey=kulak
serverUrl=http://localhost:9000
serverVersion=26.4.0.121862
dashboardUrl=http://localhost:9000/dashboard?id=kulak
ceTaskId=77035e85-cf5d-4771-ab8e-51da185429c5
ceTaskUrl=http://localhost:9000/api/ce/task?id=77035e85-cf5d-4771-ab8e-51da185429c5

4
.scribe/.filehashes Normal file
View File

@@ -0,0 +1,4 @@
# GENERATED. YOU SHOULDN'T MODIFY OR DELETE THIS FILE.
# Scribe uses this file to know when you change something manually in your docs.
.scribe/intro.md=4cce32d41499a35efb2ff125bcc4d59c
.scribe/auth.md=9bee2b1ef8a238b2e58613fa636d5f39

3
.scribe/auth.md Normal file
View File

@@ -0,0 +1,3 @@
# Authenticating requests
This API is not authenticated.

File diff suppressed because it is too large Load Diff

10920
.scribe/endpoints/00.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
# To include an endpoint that isn't a part of your Laravel app (or belongs to a vendor package),
# you can define it in a custom.*.yaml file, like this one.
# Each custom file should contain an array of endpoints. Here's an example:
# See https://scribe.knuckles.wtf/laravel/documenting/custom-endpoints#extra-sorting-groups-in-custom-endpoint-files for more options
#- httpMethods:
# - POST
# uri: api/doSomething/{param}
# metadata:
# groupName: The group the endpoint belongs to. Can be a new group or an existing group.
# groupDescription: A description for the group. You don't need to set this for every endpoint; once is enough.
# subgroup: You can add a subgroup, too.
# title: Do something
# description: 'This endpoint allows you to do something.'
# authenticated: false
# headers:
# Content-Type: application/json
# Accept: application/json
# urlParameters:
# param:
# name: param
# description: A URL param for no reason.
# required: true
# example: 2
# type: integer
# queryParameters:
# speed:
# name: speed
# description: How fast the thing should be done. Can be `slow` or `fast`.
# required: false
# example: fast
# type: string
# bodyParameters:
# something:
# name: something
# description: The things we should do.
# required: true
# example:
# - string 1
# - string 2
# type: 'string[]'
# responses:
# - status: 200
# description: 'When the thing was done smoothly.'
# content: # Your response content can be an object, an array, a string or empty.
# {
# "hey": "ho ho ho"
# }
# responseFields:
# hey:
# name: hey
# description: Who knows?
# type: string # This is optional

13
.scribe/intro.md Normal file
View File

@@ -0,0 +1,13 @@
# Introduction
<aside>
<strong>Base URL</strong>: <code>http://localhost:8080</code>
</aside>
This documentation aims to provide all the information you need to work with our API.
<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>

View File

@@ -9,9 +9,14 @@ RUN apk add --no-cache \
libpng-dev \
libjpeg-turbo-dev \
freetype-dev \
libxml2-dev \
icu-dev \
oniguruma-dev \
git \
curl \
postgresql-client \
nodejs \
npm \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) \
pdo_pgsql \
@@ -21,37 +26,73 @@ RUN apk add --no-cache \
bcmath \
gd \
exif \
pcntl
pcntl \
xml \
dom \
intl
# Configure git to allow safe directory
RUN git config --global --add safe.directory /var/www/html
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
# Copy application files
COPY --chown=www-data:www-data . .
# Copy ONLY composer files first
COPY composer.json composer.lock ./
# Remove any nested vendor directories to avoid conflicts
RUN find . -type d -name "vendor" -not -path "./vendor*" -exec rm -rf {} + 2>/dev/null || true
# Create all necessary directories
RUN mkdir -p storage/framework/{cache,sessions,views} \
# Create storage and bootstrap directories needed for composer scripts
RUN mkdir -p storage/framework/cache \
&& mkdir -p storage/framework/sessions \
&& mkdir -p storage/framework/views \
&& mkdir -p storage/framework/testing \
&& mkdir -p storage/logs \
&& mkdir -p bootstrap/cache \
&& chmod -R 777 storage \
&& chmod -R 777 bootstrap/cache
# Install dependencies
RUN composer install --no-dev --no-interaction --no-progress --optimize-autoloader --no-scripts \
&& composer run-script post-autoload-dump \
&& php artisan package:discover --ansi || true
# Configure Composer for stability on unstable networks
ENV COMPOSER_ALLOW_SUPERUSER=1 \
COMPOSER_MEMORY_LIMIT=-1 \
COMPOSER_PROCESS_TIMEOUT=2000
# Generate application key
RUN php artisan key:generate --no-interaction --force || true
# Install PHP dependencies (this layer will be cached)
RUN composer config -g repo.packagist composer https://packagist.org \
&& composer install --no-interaction --no-progress --no-scripts --prefer-dist --ignore-platform-reqs
# Isolate the clean vendor directory
#RUN mv vendor /vendor_clean
# Copy the rest of the application files (will ignore vendor because of .dockerignore)
COPY --chown=www-data:www-data . .
# Restore the clean vendor directory and set proper permissions
#RUN rm -rf vendor && mv /vendor_clean vendor && chown -R www-data:www-data vendor
# Final build verification
RUN if [ ! -f vendor/laravel/prompts/src/helpers.php ]; then \
echo "ERROR: laravel/prompts/src/helpers.php missing!" && exit 1; \
fi
# Final check and debug listing
RUN ls -l vendor/laravel/prompts/src/helpers.php \
&& du -sh vendor/laravel/prompts
# Copy package files for NPM
COPY package*.json ./
COPY vite.config.js ./
# Install NPM dependencies
RUN npm install --legacy-peer-deps --no-audit
# Build Vite assets
RUN npm run build
# Copy entrypoint script and ensure it's executable
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# Let the entrypoint handle artisan commands at runtime
EXPOSE 8000 9000
ENTRYPOINT ["/entrypoint.sh"]

51
Dockerfile2 Normal file
View File

@@ -0,0 +1,51 @@
FROM php:8.4-fpm
# 1. Setup NodeSource untuk instalasi Node.js v20 (Cepat & Stabil)
RUN apt-get update && apt-get install -y ca-certificates curl gnupg \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
# 2. Install dependencies utama dengan apt-get
RUN apt-get update && apt-get install -y \
git \
libpng-dev \
libonig-dev \
libxml2-dev \
libpq-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libzip-dev \
zip \
unzip \
nodejs \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# 3. Install PHP Extensions (TERMASUK pgsql / pdo_pgsql)
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql pdo_pgsql pgsql mbstring exif pcntl bcmath gd zip
# 4. Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
# 5. Copy existing application directory contents
COPY . /var/www
# 6. Install dependencies
# (Hapus --no-dev sementara jika Anda mau testing dengan Error Page Laravel yang rapi)
RUN composer install --no-interaction --optimize-autoloader
# 7. Install & Build Frontend
RUN npm install
RUN npm run build
# 8. Set permissions
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache \
&& chmod -R 775 /var/www/storage /var/www/bootstrap/cache
# 9. Expose port 8000 and start php artisan serve
EXPOSE 8000
# artisan serve berjalan langsung
CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8000"]

View File

@@ -4,36 +4,42 @@
use App\Models\PaymentType;
use App\Models\Product;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportBalanceSheet implements FromView
{
use DateFilterTrait;
public function view(): View
{
$businessId = auth()->user()->business_id;
$duration = request('custom_days') ? : 'today';
$fromDate = request('from_date');
$toDate = request('to_date');
$perPage = request('per_page') ?? 20;
// PRODUCT
$productQuery = Product::select('id', 'business_id', 'productName', 'product_type', 'created_at')
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
->where('business_id', $businessId);
$this->applyDateFilter($productQuery, $duration, 'created_at', $fromDate, $toDate);
$products = $productQuery->get()
->map(function ($item) {
$item->source = 'product';
return $item;
});
// BANK
$bankQuery = PaymentType::where('business_id', $businessId);
$this->applyDateFilter($bankQuery, $duration, 'opening_date', $fromDate, $toDate);
$banks = $bankQuery->get()
->map(function ($item) {
$item->source = 'bank';
return $item;
});
$asset_datas = $products->merge($banks);
$asset_datas = $products->merge($banks)->take($perPage);
// TOTAL STOCK VALUE
$total_stock_value = 0;
foreach ($products as $product) {
if (in_array($product->product_type, ['single', 'variant'])) {

View File

@@ -3,17 +3,42 @@
namespace Modules\Business\App\Exports;
use App\Models\Sale;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportBillWisePofit implements FromView
{
use DateFilterTrait;
public function view(): View
{
$profits = Sale::with('party:id,name')
->where('business_id', auth()->user()->business_id)
->latest()
->get();
$salesQuery = Sale::with('party:id,name')
->where('business_id', auth()->user()->business_id);
$salesQuery->when(request('search'), function ($query) {
$query->where(function ($q) {
$q->where('lossProfit', 'like', '%' . request('search') . '%')
->orWhere('totalAmount', 'like', '%' . request('search') . '%')
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhereHas('party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
});
$salesQuery->when(request('party_id'), function ($query, $partyId) {
if ($partyId === 'Guest') {
$query->whereNull('party_id');
} else {
$query->where('party_id', $partyId);
}
});
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
$profits = $salesQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::bill-wise-profits.excel-csv', compact('profits'));
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Modules\Business\App\Exports;
use App\Models\PaymentType;
use App\Models\Product;
use App\Models\Transaction;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportCashBalance implements FromView
{
use DateFilterTrait;
public function view(): View
{
$cash = Transaction::with('user:id,name')
->where('business_id', auth()->user()->business_id)
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($cash, $duration, 'date', request('from_date'), request('to_date'));
$cashes = $cash->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->where('date', 'like', '%' . request('search') . '%')
->orWhere('platform', 'like', '%' . request('search'). '%')
->orWhere('transaction_type', 'like', '%' . request('search') . '%')
->orWhere('amount', 'like', '%' . request('search') . '%')
->orWhereHas('user', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
})
->latest()
->limit(request('per_page') ?? 20)->get();
return view('business::cashes.excel-csv', compact('cashes'));
}
}

View File

@@ -3,14 +3,17 @@
namespace Modules\Business\App\Exports;
use App\Models\Transaction;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportCashFlowReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$cash_flows = Transaction::with([
$query = Transaction::with([
'paymentType:id,name',
'sale:id,party_id',
'sale.party:id,name',
@@ -22,11 +25,44 @@ public function view(): View
'dueCollect.party:id,name',
])
->where('business_id', auth()->user()->business_id)
->whereIn('type', ['debit', 'credit'])
->latest()
->get();
->whereIn('type', ['debit', 'credit']);
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($query, $duration, 'date', request('from_date'), request('to_date'));
// Search filter
if (request('search')) {
$query->where(function ($query) {
$query->where('date', 'like', '%' . request('search') . '%')
->orWhere('invoice_no', 'like', '%' . request('search') . '%')
->orWhere('platform', 'like', '%' . request('search') . '%')
->orWhere('amount', 'like', '%' . request('search') . '%')
->orWhere('transaction_type', 'like', '%' . request('search') . '%')
->orWhereHas('paymentType', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
// Platform filter
if (request('platform')) {
$query->where('platform', request('platform'));
}
// Paginate data
$cash_flows = $query->limit(request('per_page') ?? 20)->get();
$firstDate = $cash_flows->first()?->date;
if ($firstDate) {
$opening_balance = (clone $query)
->whereDate('date', '<', $firstDate)
->selectRaw("SUM(CASE WHEN type='credit' THEN amount ELSE 0 END) - SUM(CASE WHEN type='debit' THEN amount ELSE 0 END) as balance")
->value('balance') ?? 0;
} else {
$opening_balance = 0;
}
return view('business::cash-flow.excel-csv', compact('cash_flows', 'opening_balance'));
}

View File

@@ -11,12 +11,39 @@ class ExportComboProduct implements FromView
public function view(): View
{
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
$user = auth()->user();
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$search = request('search');
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
->where('business_id', auth()->user()->business_id)
->where('product_type', 'combo')
->withCount('combo_products as total_combo_products')
->when($search, function ($q) use ($search) {
$q->where(function ($q) use ($search) {
$q->where('productName', 'like', '%' . $search . '%')
->orWhere('productCode', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('categoryName', 'like', '%' . $search . '%');
})
->orWhereHas('unit', function ($q) use ($search) {
$q->where('unitName', 'like', '%' . $search . '%');
});
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->latest()
->get();
->limit(request('per_page') ?? 20)->get();
$combo_products->transform(function ($product) {
$product->total_stock = $product->combo_products->sum(function ($combo) {

View File

@@ -11,12 +11,39 @@ class ExportComboProductReport implements FromView
public function view(): View
{
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
$user = auth()->user();
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$search = request('search');
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
->where('business_id', auth()->user()->business_id)
->where('product_type', 'combo')
->withCount('combo_products as total_combo_products')
->when($search, function ($q) use ($search) {
$q->where(function ($q) use ($search) {
$q->where('productName', 'like', '%' . $search . '%')
->orWhere('productCode', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('categoryName', 'like', '%' . $search . '%');
})
->orWhereHas('unit', function ($q) use ($search) {
$q->where('unitName', 'like', '%' . $search . '%');
});
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->latest()
->get();
->limit(request('per_page') ?? 20)->get();
$combo_products->transform(function ($product) {
$product->total_stock = $product->combo_products->sum(function ($combo) {

View File

@@ -10,21 +10,58 @@ class ExportCurrentStock implements FromView
{
public function view(): View
{
$query = Product::with('stocks')
->where('product_type', '!=', 'combo')
->where('business_id', auth()->user()->business_id);
$businessId = auth()->user()->business_id;
$alert_qty_filter = request('alert_qty');
$search_term = request('search');
$per_page = request('per_page', 20);
if (request('alert_qty')) {
$products = $query->get()->filter(function ($product) {
$totalStock = $product->stocks->sum('productStock');
return $totalStock <= $product->alert_qty;
// Base query
$query = Product::with('stocks', 'category:id,categoryName')
->where('product_type', '!=', 'combo')
->where('business_id', $businessId);
if ($search_term) {
$query->where(function ($q) use ($search_term) {
$q->where('productName', 'like', '%' . $search_term . '%')
->orWhere('productCode', 'like', '%' . $search_term . '%')
->orWhere('hsn_code', 'like', '%' . $search_term . '%')
->orWhereHas('category', function ($q) use ($search_term) {
$q->where('categoryName', 'like', '%' . $search_term . '%');
});
});
}
if ($alert_qty_filter) {
$products = $query
->withSum('stocks as total_stock', 'productStock')
->havingRaw('total_stock <= alert_qty')
->latest()
->limit($per_page)
->get();
$total_stock_qty = $products->sum('total_stock');
$total_stock_value = $products->sum(function ($product) {
return $product->stocks->sum(function ($stock) {
return $stock->productStock * $stock->productPurchasePrice;
});
});
} else {
$products = $query->latest()->get();
$products = $query
->withSum('stocks as total_stock', 'productStock')
->latest()
->limit($per_page)
->get();
$total_stock_qty = $products->sum('total_stock');
$total_stock_value = $products->sum(function ($product) {
return $product->stocks->sum(function ($stock) {
return $stock->productStock * $stock->productPurchasePrice;
});
});
}
return view('business::stocks.excel-csv', [
'products' => $products
]);
return view('business::stocks.excel-csv', compact('products', 'total_stock_qty', 'total_stock_value'));
}
}

View File

@@ -10,13 +10,27 @@ class ExportCurrentStockReport implements FromView
{
public function view(): View
{
return view('business::reports.stocks.excel-csv', [
'stock_reports' => Product::with('stocks')
$productsQuery = Product::with(['stocks' => function ($q) {
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
}])
->where('business_id', auth()->user()->business_id)
->where('product_type', '!=', 'combo')
->withSum('stocks', 'productStock')
->where('product_type', '!=', 'combo');
if (request('search')) {
$productsQuery->where(function ($q) {
$q->where('productName', 'like', '%' . request('search') . '%')
->orWhereHas('stocks', function ($stock) {
$stock->where('productSalePrice', 'like', '%' . request('search') . '%')
->orWhere('productPurchasePrice', 'like', '%' . request('search') . '%');
});
});
}
$stock_reports = $productsQuery
->latest()
->get()
]);
->limit($request->per_page ?? 20)
->get();
return view('business::reports.stocks.excel-csv', compact('stock_reports'));
}
}

View File

@@ -13,8 +13,20 @@ public function view(): View
$customers = Party::with('sales')
->where('business_id', auth()->user()->business_id)
->where('type', '!=', 'Supplier')
->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->where('name', 'like', '%' . request('search') . '%')
->orWhere('phone', 'like', '%' . request('search') . '%')
->orWhere('type', 'like', '%' . request('search') . '%');
});
})
->when(request('type'), function ($q) {
$q->where(function ($q) {
$q->where('type', request('type'));
});
})
->latest()
->get();
->limit(request('per_page') ?? 20)->get();
$totalAmount = $customers->sum(function ($customer) {
return $customer->sales?->sum('totalAmount') ?? 0;

View File

@@ -3,14 +3,17 @@
namespace Modules\Business\App\Exports;
use App\Models\Transaction;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportDayBookReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$day_books = Transaction::with([
$query = Transaction::with([
'paymentType:id,name',
'sale:id,user_id,party_id,totalAmount',
'sale.party:id,name',
@@ -25,9 +28,34 @@ public function view(): View
'dueCollect.user:id,name',
])
->where('business_id', auth()->user()->business_id)
->whereIn('type', ['debit', 'credit'])
->latest()
->get();
->whereIn('type', ['debit', 'credit']);
// Apply date filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($query, $duration, 'date', request('from_date'), request('to_date'));
// Search filter
if (request('search')) {
$query->where(function ($query) {
$query->where('date', 'like', '%' . request('search') . '%')
->orWhere('invoice_no', 'like', '%' . request('search') . '%')
->orWhere('platform', 'like', '%' . request('search') . '%')
->orWhere('amount', 'like', '%' . request('search') . '%')
->orWhere('type', 'like', '%' . request('search') . '%')
->orWhere('transaction_type', 'like', '%' . request('search') . '%')
->orWhereHas('paymentType', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
// Platform filter
if (request('platform')) {
$query->where('platform', request('platform'));
}
// Paginate data
$day_books = $query->latest()->limit(request('per_page') ?? 20)->get();
return view('business::day-book.excel-csv', compact('day_books'));
}

View File

@@ -10,11 +10,33 @@ class ExportDiscountProduct implements FromView
{
public function view(): View
{
$discount_products = SaleDetails::with('product:id,productName,productCode')
$user = auth()->user();
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$discount_products = SaleDetails::with('product:id,productName,productCode,hsn_code')
->whereHas('product', function ($q) {
$q->where('business_id', auth()->user()->business_id);
})
->when(request('search'), function ($q) {
$q->whereHas('product', function ($q) {
$q->where('productName', 'like', '%' . request('search') . '%')
->orWhere('productCode', 'like', '%' . request('search') . '%')
->orWhere('productPurchasePrice', 'like', '%' . request('search') . '%')
->orWhere('price', 'like', '%' . request('search') . '%')
->orWhere('discount', 'like', '%' . request('search') . '%');
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('sale', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->where('discount', '>', 0)
->limit(request('per_page') ?? 20)
->get();
return view('business::reports.discount-products.excel-csv', compact('discount_products'));

View File

@@ -11,37 +11,56 @@ class ExportDue implements FromView
public function view(): View
{
$user = auth()->user();
$businessId = $user->business_id;
$activeBranch = $user->active_branch;
$business_id = $user->business_id;
$query = Party::where('business_id', $businessId)
$query = Party::where('business_id', $business_id)
->where('type', '!=', 'Supplier')
->when(request('search'), function ($q) {
$q->where(function ($q2) {
$q2->where('type', 'like', '%' . request('search') . '%')
->orWhere('name', 'like', '%' . request('search') . '%')
->orWhere('phone', 'like', '%' . request('search') . '%')
->orWhere('credit_limit', 'like', '%' . request('search') . '%');
});
})
->when(request('type'), function ($q) {
$q->where('type', request('type'));
})
->with('sales_dues')
->latest();
if ($activeBranch) {
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
$query->where('due', '>', 0);
}
$parties = $query->get();
if ($activeBranch) {
$parties->transform(function ($supplier) use ($activeBranch) {
$supplier->due = $supplier->sales_dues
$parties = $parties
->transform(function ($customer) use ($activeBranch) {
$party_due = $customer->sales_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
return $supplier;
})->filter(fn($supplier) => $supplier->due > 0);
if ($customer->branch_id === $activeBranch->id) {
$openingBalanceDue = $customer->opening_balance_type === 'due'
? ($customer->opening_balance ?? 0)
: 0;
$customer->due = $openingBalanceDue + $party_due;
} else {
$customer->due = $party_due;
}
return $customer;
})
->filter(fn($customer) => $customer->due > 0)
->take(request('per_page') ?? 20)
->values();
} else {
$parties = $parties
->filter(fn($customer) => ($customer->due ?? 0) > 0)
->take(request('per_page') ?? 20)
->values();
}
return view('business::reports.due.excel-csv', [
'parties' => $parties
]);
return view('business::reports.due.excel-csv', compact('parties'));
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace Modules\Business\App\Exports;
use App\Models\Party;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportDueList implements FromView
{
public function view(): View
{
$businessId = auth()->user()->business_id;
$activeBranch = auth()->user()->active_branch;
$query = Party::where('business_id', $businessId)
->with(['purchases_dues', 'sales_dues']);
if (request('type')) {
$query->where('type', request('type'));
}
if (request('search')) {
$search = request('search');
$query->where(function ($q) use ($search, $activeBranch) {
$q->where('type', 'like', "%$search%")
->orWhere('name', 'like', "%$search%")
->orWhere('phone', 'like', "%$search%")
->orWhere('email', 'like', "%$search%");
if (!$activeBranch) {
$q->orWhere('due', 'like', "%$search%");
}
});
}
$parties = $query->latest()->limit(request('per_page') ?? 20)->get();
if ($activeBranch) {
$parties = $parties->map(function ($party) use ($activeBranch) {
$sale_dues = $party->type === 'Supplier'
? $party->purchases_dues->where('branch_id', $activeBranch->id)
: $party->sales_dues->where('branch_id', $activeBranch->id);
$party_due = $sale_dues->sum('dueAmount');
if ($party->branch_id === $activeBranch->id) {
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
$party->due = $openingBalanceDue + $party_due;
} else {
$party->due = $party_due;
}
return $party;
})->filter(fn($p) => $p->due > 0)->values();
} else {
$parties = $parties->filter(fn($p) => $p->due > 0)->values();
}
return view('business::dues.excel-csv', [
'parties' => $parties
]);
}
}

View File

@@ -3,15 +3,48 @@
namespace Modules\Business\App\Exports;
use App\Models\Expense;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportExpense implements FromView
{
use DateFilterTrait;
public function view(): View
{
return view('business::reports.expense.excel-csv', [
'expense_reports' => Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)->latest()->get()
]);
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
$expenseQuery->when(request('branch_id'), function ($q) {
$q->where('branch_id', request('branch_id'));
});
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', request('from_date'), request('to_date'));
// Search Filter
if (request('search')) {
$expenseQuery->where(function ($query) {
$query->where('expanseFor', 'like', '%' . request('search') . '%')
->orWhere('paymentType', 'like', '%' . request('search') . '%')
->orWhere('referenceNo', 'like', '%' . request('search') . '%')
->orWhere('amount', 'like', '%' . request('search') . '%')
->orWhereHas('category', function ($q) {
$q->where('categoryName', 'like', '%' . request('search') . '%');
})
->orWhereHas('payment_type', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('branch', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
$expense_reports = $expenseQuery->latest()->limit(request('per_page' ?? 20))->get();
return view('business::reports.expense.excel-csv', compact('expense_reports'));
}
}

View File

@@ -10,16 +10,35 @@ class ExportExpiredProduct implements FromView
{
public function view(): View
{
$expired_products = Product::with('stocks', 'unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName')
$expired_products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
->where('business_id', auth()->user()->business_id)
->withSum('stocks as total_stock', 'productStock')
->whereHas('stocks', function ($query) {
$query->whereDate('expire_date', '<', today())->where('productStock', '>', 0);
$query->whereDate('expire_date', '<', today())
->where('productStock', '>', 0);
})
->latest()->get();
->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->where('type', 'like', '%' . request('search') . '%')
->orWhere('productName', 'like', '%' . request('search') . '%')
->orWhere('productCode', 'like', '%' . request('search') . '%')
->orWhere('hsn_code', 'like', '%' . request('search') . '%')
->orWhere('productSalePrice', 'like', '%' . request('search') . '%')
->orWhere('productPurchasePrice', 'like', '%' . request('search') . '%')
->orWhereHas('unit', function ($q) {
$q->where('unitName', 'like', '%' . request('search') . '%');
})
->orWhereHas('brand', function ($q) {
$q->where('brandName', 'like', '%' . request('search') . '%');
})
->orWhereHas('category', function ($q) {
$q->where('categoryName', 'like', '%' . request('search') . '%');
});
});
})
->latest()
->limit(request('per_page') ?? 20)->get();
return view('business::expired-products.excel-csv', [
'expired_products' => $expired_products
]);
return view('business::expired-products.excel-csv', compact('expired_products'));
}
}

View File

@@ -3,22 +3,52 @@
namespace Modules\Business\App\Exports;
use App\Models\Product;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportExpiredProductReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
return view('business::reports.expired-products.excel-csv', [
'expired_products' => Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
$businessId = auth()->user()->business_id;
$expiredProductsQuery = Product::with(['unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks'])
->withSum('stocks', 'productStock')
->where('business_id', auth()->user()->business_id)
->where('business_id', $businessId)
->whereHas('stocks', function ($query) {
$query->whereDate('expire_date', '<', today())->where('productStock', '>', 0);
$query->whereDate('expire_date', '<=', today())->where('productStock', '>', 0);
});
// Date Filter
$duration = request('custom_days') ?: 'today';
$expiredProductsQuery->whereHas('stocks', function ($q) use ($duration) {
$this->applyDateFilter($q, $duration, 'expire_date', request('from_date'), request('to_date'));
});
// Search Filter
if (request('search')) {
$search = request('search');
$expiredProductsQuery->where(function ($query) use ($search) {
$query->where('productName', 'like', '%' . $search . '%')
->orWhere('productCode', 'like', '%' . $search . '%')
->orWhere('productPurchasePrice', 'like', '%' . $search . '%')
->orWhere('productSalePrice', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('categoryName', 'like', '%' . $search . '%');
})
->latest()
->get()
]);
->orWhereHas('brand', function ($q) use ($search) {
$q->where('brandName', 'like', '%' . $search . '%');
})
->orWhereHas('unit', function ($q) use ($search) {
$q->where('unitName', 'like', '%' . $search . '%');
});
});
}
$expired_products = $expiredProductsQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::reports.expired-products.excel-csv', compact('expired_products'));
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Modules\Business\App\Exports;
use App\Models\Sale;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportGuestDue implements FromView
{
public function view(): View
{
$walk_in_customers = Sale::where('business_id', auth()->user()->business_id)
->with('dueCollect')
->whereNull('party_id')
->where('dueAmount', '>', 0)
->when(request('search'), function ($query) {
$query->where(function ($q) {
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
->orwhere('dueAmount', 'like', '%' . request('search') . '%');
});
})
->latest()
->limit(request('per_page') ?? 20)->get();
return view('business::walk-dues.excel-csv', compact('walk_in_customers'));
}
}

View File

@@ -3,15 +3,44 @@
namespace Modules\Business\App\Exports;
use App\Models\Income;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportIncome implements FromView
{
use DateFilterTrait;
public function view(): View
{
return view('business::reports.income.excel-csv', [
'income_reports' => Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)->latest()->get()
]);
$incomeQuery = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
// Branch filter
if (request('branch_id')) {
$incomeQuery->where('branch_id', request('branch_id'));
}
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', request('from_date'), request('to_date'));
// Search filter
if (request('search')) {
$search = request('search');
$incomeQuery->where(function ($query) use ($search) {
$query->where('incomeFor', 'like', '%' . $search . '%')
->orWhere('paymentType', 'like', '%' . $search . '%')
->orWhere('amount', 'like', '%' . $search . '%')
->orWhere('referenceNo', 'like', '%' . $search . '%')
->orWhereHas('category', fn($q) => $q->where('categoryName', 'like', '%' . $search . '%'))
->orWhereHas('payment_type', fn($q) => $q->where('name', 'like', '%' . $search . '%'))
->orWhereHas('branch', fn($q) => $q->where('name', 'like', '%' . $search . '%'));
});
}
$income_reports = $incomeQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::reports.income.excel-csv', compact('income_reports'));
}
}

View File

@@ -2,51 +2,79 @@
namespace Modules\Business\App\Exports;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Concerns\FromView;
class ExportLossProfitHistory implements FromView
{
use DateFilterTrait;
public function view(): View
{
$user = auth()->user();
$businessId = $user->business_id;
$perPage = request('per_page') ?? 20;
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
// SALES
$dailySales = DB::table('sales')
$duration = request('custom_days') ?: 'today';
$salesQuery = DB::table('sales')
->select(
DB::raw('DATE(saleDate) as date'),
DB::raw('"saleDate"::date as date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END as profit_type
"),
DB::raw('SUM(actual_total_amount) as total_sales'),
DB::raw('SUM(lossProfit) as total_sale_income')
DB::raw('SUM("lossProfit") as total_sale_income')
)
->where('business_id', $businessId)
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(saleDate)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(
DB::raw('"saleDate"::date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END
")
);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
$dailySales = $salesQuery->limit($perPage)->get();
$sale_datas = $dailySales->map(fn ($sale) => (object)[
'type' => 'Sale',
'date' => $sale->date,
'profit_type' => $sale->profit_type,
'total_sales' => $sale->total_sales,
'total_incomes' => $sale->total_sale_income,
]);
// INCOME
$dailyIncomes = DB::table('incomes')
$incomeQuery = DB::table('incomes')
->select(
DB::raw('DATE(incomeDate) as date'),
DB::raw('"incomeDate"::date as date'),
DB::raw('SUM(amount) as total_incomes')
)
->where('business_id', $businessId)
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(incomeDate)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('"incomeDate"::date'));
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', request('from_date'), request('to_date'));
$dailyIncomes = $incomeQuery->limit($perPage)->get();
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
'type' => 'Income',
@@ -54,46 +82,66 @@ public function view(): View
'total_incomes' => $income->total_incomes,
]);
// MERGE SALE + INCOME
$mergedIncomeSaleData = collect();
$allDates = $dailySales->pluck('date')->merge($dailyIncomes->pluck('date'))->unique()->sort();
$allDates = $dailySales->pluck('date')
->merge($dailyIncomes->pluck('date'))
->unique()
->sort();
foreach ($allDates as $date) {
if ($income = $income_datas->firstWhere('date', $date)) {
$mergedIncomeSaleData->push($income);
}
if ($sale = $sale_datas->firstWhere('date', $date)) {
// multiple sale rows handle
$salesOfDate = $sale_datas->where('date', $date);
foreach ($salesOfDate as $sale) {
$mergedIncomeSaleData->push($sale);
}
}
// PAYROLL
$dailyPayrolls = collect();
if (moduleCheck('HrmAddon')) {
$dailyPayrolls = DB::table('payrolls')
$payrollQuery = DB::table('payrolls')
->select(
DB::raw('DATE(date) as date'),
DB::raw('"date"::date as date'),
DB::raw('SUM(amount) as total_payrolls')
)
->where('business_id', $businessId)
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(date)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('"date"::date'));
$this->applyDateFilter($payrollQuery, $duration, 'date', request('from_date'), request('to_date'));
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
}
// EXPENSES
$dailyExpenses = DB::table('expenses')
$expenseQuery = DB::table('expenses')
->select(
DB::raw('DATE(expenseDate) as date'),
DB::raw('"expenseDate"::date as date'),
DB::raw('SUM(amount) as total_expenses_only')
)
->where('business_id', $businessId)
->when($branchId, fn($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(expenseDate)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('"expenseDate"::date'));
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', request('from_date'), request('to_date'));
$dailyExpenses = $expenseQuery->limit($perPage)->get();
$mergedExpenseData = collect();
$allExpenseDates = $dailyExpenses->pluck('date')->merge($dailyPayrolls->pluck('date'))->unique()->sort();
$allExpenseDates = $dailyExpenses->pluck('date')
->merge($dailyPayrolls->pluck('date'))
->unique()
->sort();
foreach ($allExpenseDates as $date) {
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
$mergedExpenseData->push((object)[
'type' => 'Expense',
@@ -101,6 +149,7 @@ public function view(): View
'total_expenses' => $expense->total_expenses_only,
]);
}
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
$mergedExpenseData->push((object)[
'type' => 'Payroll',
@@ -110,9 +159,9 @@ public function view(): View
}
}
// SUMMARY
$grossSaleProfit = $sale_datas->sum('total_sales');
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
$totalExpenses = $mergedExpenseData->sum('total_expenses');
$netProfit = $grossIncomeProfit - $totalExpenses;

View File

@@ -13,7 +13,13 @@ public function view(): View
$parties = Party::with('sales')
->where('business_id', auth()->user()->business_id)
->where('type', '!=', 'Supplier')
->when(request('search'), function ($query) {
$query->where(function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
})
->latest()
->limit(request('per_page') ?? 20)
->get();
return view('business::party-reports.loss-profit.excel-csv', compact('parties'));

View File

@@ -8,10 +8,61 @@
class ExportProduct implements FromView
{
public function view(): View
{
$products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName')->where('business_id', auth()->user()->business_id)->withSum('stocks as total_stock', 'productStock')->latest()->get();
$user = auth()->user();
$search = request('search');
$products = Product::query()
->where('business_id', $user->business_id)
->with([
'stocks',
'unit:id,unitName',
'brand:id,brandName',
'category:id,categoryName',
'warehouse:id,name',
'rack:id,name',
'shelf:id,name',
'combo_products.stock.product:id,productName'
])
->withSum('stocks as total_stock', 'productStock')
->where(function ($query) {
$query->where('product_type', '!=', 'combo')
->orWhere(function ($q) {
$q->where('product_type', 'combo')
->whereHas('combo_products');
});
})
->when($search, function ($q) use ($search) {
$q->where(function ($q) use ($search) {
$q->where('productName', 'like', "%{$search}%")
->orWhere('productCode', 'like', "%{$search}%")
->orWhere('hsn_code', 'like', "%{$search}%")
->orWhere('productPurchasePrice', 'like', "%{$search}%")
->orWhere('productSalePrice', 'like', "%{$search}%")
->orWhere('product_type', 'like', "%{$search}%")
->orWhereHas('category', fn ($q) => $q->where('categoryName', 'like', "%{$search}%"))
->orWhereHas('brand', fn ($q) => $q->where('brandName', 'like', "%{$search}%"))
->orWhereHas('unit', fn ($q) => $q->where('unitName', 'like', "%{$search}%"));
});
})
->latest()
->limit(request('per_page') ?? 20)
->get();
$products = $products->transform(function ($product) {
if ($product->product_type === 'combo') {
$product->total_stock = $product->combo_products->sum(
fn ($combo) => $combo->stock?->productStock ?? 0
);
$product->total_cost = $product->combo_products->sum(
fn ($combo) => ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0)
);
}
return $product;
});
return view('business::products.excel-csv', [
'products' => $products

View File

@@ -11,23 +11,35 @@ class ExportProductLossProfit implements FromView
{
public function view(): View
{
$branchId = moduleCheck('MultiBranchAddon') ? auth()->user()->branch_id ?? auth()->user()->active_branch_id : null;
$user = auth()->user();
$branchId = $user->branch_id ?? $user->active_branch_id;
$product_lossProfits = SaleDetails::with('product:id,productName,productCode')
->whereHas('product', function ($q) {
$q->where('business_id', auth()->user()->business_id);
$baseQuery = SaleDetails::query()
->whereHas(
'product',
fn($q) =>
$q->where('business_id', $user->business_id)
)
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
$q->whereHas('sale', fn($q) => $q->where('branch_id', $branchId));
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('sale', function ($sale) use ($branchId) {
$sale->where('branch_id', $branchId);
->when(request('search'), function ($q) {
$q->whereHas('product', function ($q) {
$q->where('productName', 'like', '%' . request('search') . '%')
->orWhere('productCode', 'like', '%' . request('search') . '%')
->orWhere('hsn_code', 'like', '%' . request('search') . '%');
});
})
});
$product_lossProfits = $baseQuery
->with('product:id,productName,productCode,hsn_code')
->select(
'product_id',
DB::raw('SUM(CASE WHEN lossProfit > 0 THEN lossProfit ELSE 0 END) as profit'),
DB::raw('SUM(CASE WHEN lossProfit < 0 THEN lossProfit ELSE 0 END) as loss')
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) AS profit'),
DB::raw('SUM(CASE WHEN "lossProfit" < 0 THEN "lossProfit" ELSE 0 END) AS loss')
)
->groupBy('product_id')
->limit(request('per_page') ?? 20)
->get();
return view('business::reports.product-loss-profit.excel-csv', compact('product_lossProfits'));

View File

@@ -3,29 +3,54 @@
namespace Modules\Business\App\Exports;
use App\Models\Product;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportProductPurchaseHistoryDetailReport implements FromView
{
protected $id;
use DateFilterTrait;
public function __construct($id)
protected string $id;
public function __construct(string $id)
{
$this->id = $id;
}
public function view(): View
{
$businessId = auth()->user()->business_id;
$duration = request('custom_days') ?: 'today';
$product = Product::select('id', 'business_id', 'productName')
->where('business_id', auth()->user()->business_id)
->where('business_id', $businessId)
->findOrFail($this->id);
$purchaseDetailsQuery = $product->purchaseDetails()
->with('purchase:id,invoiceNumber,purchaseDate')
->whereHas('purchase', function ($purchase) use ($duration) {
$this->applyDateFilter($purchase, $duration, 'purchaseDate', request('from_date'), request('to_date'));
})
->with('purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
->select('id', 'purchase_id', 'product_id', 'quantities', 'productPurchasePrice');
$purchaseDetails = $purchaseDetailsQuery->get();
$purchaseDetailsQuery->when(request('search'), function ($q) {
$search = request('search');
$q->where(function ($q) use ($search) {
$q->where('productPurchasePrice', 'like', "%{$search}%")
->orWhere('quantities', 'like', "%{$search}%")
->orWhereHas('purchase', function ($q) use ($search) {
$q->where('invoiceNumber', 'like', "%{$search}%")
->orWhere('purchaseDate', 'like', "%{$search}%");
})
->orWhereHas('purchase.party', function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
});
}
);
$purchaseDetails = $purchaseDetailsQuery->limit(request('per_page') ?? 20)->get();
return view('business::product-purchase-history-report.excel-csv-detail', compact('product', 'purchaseDetails'));
}

View File

@@ -3,17 +3,30 @@
namespace Modules\Business\App\Exports;
use App\Models\Product;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportProductPurchaseHistoryReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$businessId = auth()->user()->business_id;
$duration = request('custom_days') ?: 'today';
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
$products = $productQuery->get();
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'purchaseDetails.purchase', 'stocks', 'combo_products'])
->where('business_id', $businessId)
->whereHas('purchaseDetails.purchase', function ($purchase) use ($duration) {
$this->applyDateFilter($purchase, $duration, 'purchaseDate', request('from_date'), request('to_date'));
});
$productQuery->when(request('search'), function ($q) {
$q->where('productName', 'like', '%' . $request->search . '%');
});
$products = $productQuery->limit(request('per_page') ?? 20)->get();
$total_purchase_qty = $products->sum(function ($product) {
return $product->purchaseDetails->sum('quantities');

View File

@@ -2,21 +2,44 @@
namespace Modules\Business\App\Exports;
use App\Models\Product;
use App\Models\PurchaseDetails;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportProductPurchaseReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$product_purchases = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
$query = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
->whereHas('purchase', function ($q) {
$q->where('business_id', auth()->user()->business_id);
});
// Date Filter
$duration = request('custom_days') ?: 'today';
$query->whereHas('purchase', function ($q) use ($duration) {
$this->applyDateFilter($q, $duration, 'purchaseDate', request('from_date'), request('to_date'));
});
$query->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->whereHas('product', function ($q) {
$q->where('productName', 'like', '%' . request('search') . '%');
})
->get();
->orWhereHas('purchase', function ($q) {
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhere('purchaseDate', 'like', '%' . request('search') . '%');
})
->orWhereHas('purchase.party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
});
$product_purchases = $query->limit(request('per_page') ?? 20)->get();
return view('business::reports.product-purchase.excel-csv', compact('product_purchases'));
}

View File

@@ -3,29 +3,53 @@
namespace Modules\Business\App\Exports;
use App\Models\Product;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportProductSaleHistoryDetailReport implements FromView
{
protected $id;
use DateFilterTrait;
public function __construct($id)
protected string $id;
public function __construct(string $id)
{
$this->id = $id;
}
public function view(): View
{
$businessId = auth()->user()->business_id;
$duration = request('custom_days') ?: 'today';
$product = Product::select('id', 'business_id', 'productName')
->where('business_id', auth()->user()->business_id)
->where('business_id', $businessId)
->findOrFail($this->id);
$saleDetailsQuery = $product->saleDetails()
->whereHas('sale', function ($sale) use ($duration) {
$this->applyDateFilter($sale, $duration, 'saleDate', request('from_date'), request('to_date'));
})
->with('sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
->select('id', 'sale_id', 'product_id', 'quantities', 'lossprofit', 'price', 'productPurchasePrice');
$saleDetails = $saleDetailsQuery->get();
$saleDetailsQuery->when(request('search'), function ($q) {
$search = request('search');
$q->where(function ($q) use ($search) {
$q->where('price', 'like', "%{$search}%")
->orWhere('quantities', 'like', "%{$search}%")
->orWhereHas('sale', function ($q) use ($search) {
$q->where('invoiceNumber', 'like', "%{$search}%")
->orWhere('saleDate', 'like', "%{$search}%");
})
->orWhereHas('sale.party', function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
});
}
);
$saleDetails = $saleDetailsQuery->limit(request('per_page') ?? 20)->get();
return view('business::product-sale-history-report.excel-csv-detail', compact('product', 'saleDetails'));
}

View File

@@ -3,17 +3,30 @@
namespace Modules\Business\App\Exports;
use App\Models\Product;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportProductSaleHistoryReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$businessId = auth()->user()->business_id;
$duration = request('custom_days') ?: 'today';
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
$products = $productQuery->get();
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'saleDetails.sale', 'stocks', 'combo_products'])
->where('business_id', $businessId)
->whereHas('saleDetails.sale', function ($sale) use ($duration) {
$this->applyDateFilter($sale, $duration, 'saleDate', request('from_date'), request('to_date'));
});
$productQuery->when(request('search'), function ($q) {
$q->where('productName', 'like', '%' . request('search') . '%');
});
$products = $productQuery->limit(request('per_page') ?? 20)->get();
$total_single_sale_price = $products->sum(function ($product) {
return $product->saleDetails->sum('price');

View File

@@ -3,18 +3,45 @@
namespace Modules\Business\App\Exports;
use App\Models\Sale;
use App\Models\SaleDetails;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportProductSaleReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$product_sales = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
->where('business_id', auth()->user()->business_id)
->latest()
->get();
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
->whereHas('sale', function ($q) {
$q->where('business_id', auth()->user()->business_id);
});
// Date Filter
$duration = request('custom_days') ?: 'today';
$query->whereHas('sale', function ($q) use ($duration) {
$this->applyDateFilter($q, $duration, 'saleDate', request('from_date'), request('to_date'));
});
// Search Filter
$query->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->whereHas('product', function ($q) {
$q->where('productName', 'like', '%' . request('search') . '%');
})
->orWhereHas('sale', function ($q) {
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhere('saleDate', 'like', '%' . request('search') . '%');
})
->orWhereHas('sale.party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
});
$product_sales = $query->limit(request('per_page') ?? 20)->get();
return view('business::reports.product-sale.excel-csv', compact('product_sales'));
}

View File

@@ -3,14 +3,17 @@
namespace Modules\Business\App\Exports;
use App\Models\Purchase;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportPurchaseReturn implements FromView
{
use DateFilterTrait;
public function view(): View
{
$purchases = Purchase::with([
$purchasesQuery = Purchase::with([
'user:id,name',
'branch:id,name',
'party:id,name,email,phone,type',
@@ -22,9 +25,32 @@ public function view(): View
}
])
->where('business_id', auth()->user()->business_id)
->whereHas('purchaseReturns')
->latest()
->get();
->whereHas('purchaseReturns');
$purchasesQuery->when(request('branch_id'), function ($q) {
$q->where('branch_id', request('branch_id'));
});
// Date Filter
$duration = request('custom_days') ?: 'today';
$purchasesQuery->whereHas('purchaseReturns', function ($query) use ($duration) {
$this->applyDateFilter($query, $duration, 'return_date', request('from_date'), request('to_date'));
});
// Search Filter
if (request('search')) {
$purchasesQuery->where(function ($query) {
$query->where('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhereHas('party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('branch', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
$purchases = $purchasesQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::reports.purchase-return.excel-csv', compact('purchases'));
}

View File

@@ -3,16 +3,46 @@
namespace Modules\Business\App\Exports;
use App\Models\Sale;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportSaleReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$sales = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
->latest()
->get();
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
$salesQuery->when(request('branch_id'), function ($q) {
$q->where('branch_id', request('branch_id'));
});
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
// Search Filter
if (request('search')) {
$salesQuery->where(function ($query) {
$query->where('paymentType', 'like', '%' . request('search') . '%')
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhereHas('party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('payment_type', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('branch', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
$sales = $salesQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::reports.sales.excel', compact('sales'));
}

View File

@@ -3,14 +3,17 @@
namespace Modules\Business\App\Exports;
use App\Models\Sale;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportSalesReturn implements FromView
{
use DateFilterTrait;
public function view(): View
{
$sales = Sale::with([
$salesQuery = Sale::with([
'user:id,name',
'party:id,name',
'branch:id,name',
@@ -23,9 +26,30 @@ public function view(): View
}
])
->where('business_id', auth()->user()->business_id)
->whereHas('saleReturns')
->latest()
->get();
->when(request('branch_id'), function ($q) {
$q->where('branch_id', request('branch_id'));
})->whereHas('saleReturns');
// Date Filter
$duration = request('custom_days') ?: 'today';
$salesQuery->whereHas('saleReturns', function ($query) use ($duration) {
$this->applyDateFilter($query, $duration, 'return_date', request('from_date'), request('to_date'));
});
// Search Filter
if (request('search')) {
$salesQuery->where(function ($query) {
$query->where('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhereHas('party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('branch', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
$sales = $salesQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::reports.sales-return.excel-csv', compact('sales'));
}

View File

@@ -2,15 +2,17 @@
namespace Modules\Business\App\Exports;
use App\Models\Party;
use Maatwebsite\Excel\Concerns\FromView;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection;
class ExportSingleCustomerLedger implements FromView
{
public $ledger;
public $party;
public Collection $ledger;
public Party $party;
public function __construct($ledger, $party)
public function __construct(Collection $ledger, Party $party)
{
$this->ledger = $ledger;
$this->party = $party;

View File

@@ -2,15 +2,17 @@
namespace Modules\Business\App\Exports;
use App\Models\Party;
use Maatwebsite\Excel\Concerns\FromView;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection;
class ExportSingleSupplierLedger implements FromView
{
public $ledger;
public $party;
public Collection $ledger;
public Party $party;
public function __construct($ledger, $party)
public function __construct(Collection $ledger, Party $party)
{
$this->ledger = $ledger;
$this->party = $party;

View File

@@ -3,15 +3,44 @@
namespace Modules\Business\App\Exports;
use App\Models\PlanSubscribe;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportSubscription implements FromView
{
use DateFilterTrait;
public function view(): View
{
return view('business::reports.subscription-reports.excel-csv', [
'subscribers' => PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id)->latest()->get()
]);
$subscriberQuery = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id);
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($subscriberQuery, $duration, 'created_at', request('from_date'), request('to_date'));
// Search Filter
if (request('search')) {
$search = request('search');
$subscriberQuery->where(function ($query) use ($search) {
$query->where('duration', 'like', '%' . $search . '%')
->orWhereHas('plan', function ($q) use ($search) {
$q->where('subscriptionName', 'like', '%' . $search . '%');
})
->orWhereHas('gateway', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('business', function ($q) use ($search) {
$q->where('companyName', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
});
});
});
}
$subscribers = $subscriberQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::reports.subscription-reports.excel-csv', compact('subscribers'));
}
}

View File

@@ -16,31 +16,48 @@ public function view(): View
$query = Party::where('business_id', $businessId)
->where('type', 'Supplier')
->when(request('search'), function ($q) {
$q->where(function ($q2) {
$q2->where('type', 'like', '%' . request('search') . '%')
->orWhere('name', 'like', '%' . request('search') . '%')
->orWhere('phone', 'like', '%' . request('search') . '%')
->orWhere('credit_limit', 'like', '%' . request('search') . '%');
});
})
->with('purchases_dues')
->latest();
if ($activeBranch) {
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
$query->where('due', '>', 0);
}
$parties = $query->get();
if ($activeBranch) {
$parties->transform(function ($supplier) use ($activeBranch) {
$supplier->due = $supplier->purchases_dues
$parties = $parties
->transform(function ($supplier) use ($activeBranch) {
$party_due = $supplier->purchases_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
return $supplier;
})->filter(fn($supplier) => $supplier->due > 0);
if ($supplier->branch_id === $activeBranch->id) {
$openingBalanceDue = $supplier->opening_balance_type === 'due'
? ($supplier->opening_balance ?? 0)
: 0;
$supplier->due = $openingBalanceDue + $party_due;
} else {
$supplier->due = $party_due;
}
return view('business::reports.supplier-due.excel-csv', [
'parties' => $parties
]);
return $supplier;
})
->filter(fn($supplier) => $supplier->due > 0)
->take(request('per_page') ?? 20)
->values();
} else {
$parties = $parties
->filter(fn($supplier) => ($supplier->due ?? 0) > 0)
->take(request('per_page') ?? 20)
->values();
}
return view('business::reports.supplier-due.excel-csv', compact('parties'));
}
}

View File

@@ -13,8 +13,15 @@ public function view(): View
$suppliers = Party::with('purchases')
->where('business_id', auth()->user()->business_id)
->where('type', '=', 'Supplier')
->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->where('name', 'like', '%' . request('search') . '%')
->orWhere('phone', 'like', '%' . request('search') . '%')
->orWhere('type', 'like', '%' . request('search') . '%');
});
})
->latest()
->get();
->limit(request('per_page') ?? 20)->get();
$totalAmount = $suppliers->sum(function ($customer) {
return $customer->purchases?->sum('totalAmount') ?? 0;

View File

@@ -0,0 +1,211 @@
<?php
namespace Modules\Business\App\Exports;
use App\Models\Purchase;
use App\Models\PurchaseReturnDetail;
use App\Models\Sale;
use App\Models\SaleDetails;
use App\Models\SaleReturnDetails;
use App\Models\Vat;
use App\Models\VatTransaction;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportTaxReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$businessId = auth()->user()->business_id;
$type = request('type') ?? 'sales';
$duration = request('custom_days') ?: 'today';
// SALES QUERY
$salesQuery = Sale::with('party', 'payment_type', 'transactions')
->where('business_id', $businessId);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', request('from_date'), request('to_date'));
if (request('search')) {
$search = request('search');
$salesQuery->where(function ($query) use ($search) {
$query->where('invoiceNumber', 'like', '%' . $search . '%')
->orWhere('totalAmount', 'like', '%' . $search . '%')
->orWhere('discountAmount', 'like', '%' . $search . '%')
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
});
}
$salesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
->where('vat_transactions.vatable_type', SaleDetails::class)
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
->where('sales.business_id', $businessId)
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
->groupBy('vat_transactions.vat_id')
->pluck('total','vat_transactions.vat_id')
->toArray();
$salesReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
->join('sale_return_details', 'sale_return_details.id', '=', 'vat_transactions.vatable_id')
->join('sale_details', 'sale_details.id', '=', 'sale_return_details.sale_detail_id')
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
->where('sales.business_id', $businessId)
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
->groupBy('vat_transactions.vat_id')
->pluck('total', 'vat_transactions.vat_id')
->toArray();
$saleVatRowMap = VatTransaction::where('business_id', $businessId)
->where('vatable_type', \App\Models\SaleDetails::class)
->whereIn('vatable_id', function ($query) use ($businessId, $duration) {
$query->select('sale_details.id')
->from('sale_details')
->join('sales', 'sales.id', '=', 'sale_details.sale_id')
->where('sales.business_id', $businessId);
if ($duration === 'custom_days' && request('from_date') && request('to_date')) {
$query->whereBetween('sales.saleDate', [request('from_date'), request('to_date')]);
}
})
->join('sale_details', 'sale_details.id', '=', 'vat_transactions.vatable_id')
->selectRaw('sale_details.sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
->groupBy('sale_details.sale_id', 'vat_transactions.vat_id')
->get()
->groupBy('sale_id')
->map(function ($items) {
return $items->pluck('total', 'vat_id')->toArray();
})
->toArray();
$saleReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
->where('vat_transactions.vatable_type', SaleReturnDetails::class)
->join('sale_return_details','sale_return_details.id','=','vat_transactions.vatable_id')
->join('sale_details','sale_details.id','=','sale_return_details.sale_detail_id')
->join('sales','sales.id','=','sale_details.sale_id')
->selectRaw('sales.id as sale_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
->groupBy('sales.id','vat_transactions.vat_id')
->get();
$saleReturnVatRowMap = $saleReturnVatRows
->groupBy('sale_id')
->map(fn($rows)=>$rows->pluck('vat_amount','vat_id'))
->toArray();
// PURCHASE QUERY
$purchasesQuery = Purchase::with('party', 'payment_type', 'transactions')
->where('business_id', $businessId);
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', request('from_date'), request('to_date'));
if (request('search')) {
$search = request('search');
$purchasesQuery->where(function ($query) use ($search) {
$query->where('invoiceNumber', 'like', '%' . $search . '%')
->orWhere('totalAmount', 'like', '%' . $search . '%')
->orWhere('discountAmount', 'like', '%' . $search . '%')
->orWhereHas('party', fn($q) => $q->where('name', 'like', '%' . $search . '%')->orWhere('tax_no', 'like', '%' . $search . '%'));
});
}
$purchasesVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
->where('vat_transactions.vatable_type', \App\Models\PurchaseDetails::class)
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
->where('purchases.business_id', $businessId)
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
->groupBy('vat_transactions.vat_id')
->pluck('total','vat_transactions.vat_id')
->toArray();
$purchaseReturnVatTotals = VatTransaction::where('vat_transactions.business_id', $businessId)
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
->join('purchase_return_details', 'purchase_return_details.id', '=', 'vat_transactions.vatable_id')
->join('purchase_details', 'purchase_details.id', '=', 'purchase_return_details.purchase_detail_id')
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
->where('purchases.business_id', $businessId)
->selectRaw('vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
->groupBy('vat_transactions.vat_id')
->pluck('total', 'vat_transactions.vat_id')
->toArray();
$purchaseVatRowMap = VatTransaction::where('business_id', $businessId)
->where('vatable_type', \App\Models\PurchaseDetails::class)
->whereIn('vatable_id', function ($query) use ($businessId, $duration) {
$query->select('purchase_details.id')
->from('purchase_details')
->join('purchases', 'purchases.id', '=', 'purchase_details.purchase_id')
->where('purchases.business_id', $businessId);
if ($duration === 'custom_date' && request('from_date') && request('to_date')) {
$query->whereBetween('purchases.purchaseDate', [request('from_date'), request('to_date')]);
}
})
->join('purchase_details', 'purchase_details.id', '=', 'vat_transactions.vatable_id')
->selectRaw('purchase_details.purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as total')
->groupBy('purchase_details.purchase_id', 'vat_transactions.vat_id')
->get()
->groupBy('purchase_id')
->map(function ($items) {
return $items->pluck('total', 'vat_id')->toArray();
})
->toArray();
$purchaseReturnVatRows = VatTransaction::where('vat_transactions.business_id', $businessId)
->where('vat_transactions.vatable_type', PurchaseReturnDetail::class)
->join('purchase_return_details','purchase_return_details.id','=','vat_transactions.vatable_id')
->join('purchase_details','purchase_details.id','=','purchase_return_details.purchase_detail_id')
->join('purchases','purchases.id','=','purchase_details.purchase_id')
->selectRaw('purchases.id as purchase_id, vat_transactions.vat_id, SUM(vat_transactions.vat_amount) as vat_amount')
->groupBy('purchases.id','vat_transactions.vat_id')
->get();
$purchaseReturnVatRowMap = $purchaseReturnVatRows
->groupBy('purchase_id')
->map(fn($rows) => $rows->pluck('vat_amount','vat_id'))
->toArray();
// TAB CONTROL
$sales = collect();
$purchases = collect();
$limit = request('per_page') ?? 20;
if ($type === 'sales') {
$sales = $salesQuery->latest()->limit($limit)->get();
}
if ($type === 'purchases') {
$purchases = $purchasesQuery->latest()->limit($limit)->get();
}
$vats = Vat::where('business_id', $businessId)->get();
return view('business::reports.vats.excel-csv',
compact(
'sales',
'salesVatTotals',
'salesReturnVatTotals',
'saleVatRowMap',
'saleReturnVatRowMap',
'purchases',
'purchasesVatTotals',
'purchaseReturnVatTotals',
'purchaseVatRowMap',
'purchaseReturnVatRowMap',
'vats',
'type'
)
);
}
}

View File

@@ -14,10 +14,23 @@ public function view(): View
->where('business_id', auth()->user()->business_id)
->where('type', '!=', 'Supplier')
->whereHas('sales')
->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->where('name', 'like', '%' . request('search') . '%')
->orWhere('phone', 'like', '%' . request('search') . '%')
->orWhere('email', 'like', '%' . request('search') . '%')
->orWhere('type', 'like', '%' . request('search') . '%');
});
})
->withCount('sales')
->withSum('sales', 'totalAmount')
->orderByDesc('sales_count')
->orderByDesc('sales_sum_total_amount')
->when(request('type'), function ($q) {
$q->where(function ($q) {
$q->where('type', request('type'));
});
})
->take(5)
->get();

View File

@@ -11,25 +11,38 @@ class ExportTopProduct implements FromView
{
public function view(): View
{
$branchId = moduleCheck('MultiBranchAddon') ? auth()->user()->branch_id ?? auth()->user()->active_branch_id : null;
$user = auth()->user();
$businessId = $user->business_id;
$top_products = SaleDetails::with('product:id,productName,productCode')
->whereHas('product', function ($q) {
$q->where('business_id', auth()->user()->business_id);
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$top_products = SaleDetails::query()
->with('product:id,productName,productCode,hsn_code')
->whereHas('product', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
})
->when(request('search'), function ($q) {
$q->whereHas('product', function ($q) {
$q->where('productName', 'like', '%' . request('search') . '%')
->orWhere('productCode', 'like', '%' . request('search') . '%');
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('sale', function ($sale) use ($branchId) {
$sale->where('branch_id', $branchId);
$q->whereHas('sale', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->select(
'product_id',
DB::raw('SUM(quantities) as total_sold_qty'),
DB::raw('SUM(price * quantities) as total_sale_amount')
DB::raw('SUM((price - discount) * quantities) as total_sale_amount')
)
->groupBy('product_id')
->orderByDesc('total_sold_qty')
->take(5)
->limit(5)
->get();
return view('business::reports.top-products.excel-csv', compact('top_products'));

View File

@@ -14,6 +14,14 @@ public function view(): View
->where('business_id', auth()->user()->business_id)
->where('type', '=', 'Supplier')
->whereHas('purchases')
->when(request('search'), function ($q) {
$q->where(function ($q) {
$q->where('name', 'like', '%' . request('search') . '%')
->orWhere('phone', 'like', '%' . request('search') . '%')
->orWhere('email', 'like', '%' . request('search') . '%')
->orWhere('type', 'like', '%' . request('search') . '%');
});
})
->withCount('purchases')
->withSum('purchases', 'totalAmount')
->orderByDesc('purchases_count')

View File

@@ -3,15 +3,49 @@
namespace Modules\Business\App\Exports;
use App\Models\DueCollect;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportTransaction implements FromView
{
use DateFilterTrait;
public function view(): View
{
return view('business::reports.transaction-history.excel-csv', [
'transactions' => DueCollect::where('business_id', auth()->user()->business_id)->with('party:id,name,type', 'payment_type:id,name', 'transactions')->latest()->get()
]);
$businessId = auth()->user()->business_id;
$transactionsQuery = DueCollect::with('party:id,name,type', 'payment_type:id,name', 'transactions')->where('business_id', $businessId);
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($transactionsQuery, $duration, 'paymentDate', request('from_date'), request('to_date'));
// Search Filter
if (request('search')) {
$transactionsQuery->where(function ($query) {
$query->where('paymentType', 'like', '%' . request('search') . '%')
->orWhere('totalDue', 'like', '%' . request('search') . '%')
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhere('payDueAmount', 'like', '%' . request('search') . '%')
->orWhereHas('party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('payment_type', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
if (request('type')) {
$transactionsQuery->whereHas('party', function ($q) {
$q->where(function ($q) {
$q->where('type', request('type'));
});
});
}
$transactions = $transactionsQuery->latest()->limit(request('per_page'))->get();
return view('business::reports.transaction-history.excel-csv', compact('transactions'));
}
}

View File

@@ -3,17 +3,82 @@
namespace Modules\Business\App\Exports;
use App\Models\Transaction;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class ExportTransactionReport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$transactions = Transaction::with('paymentType')
->where('business_id', auth()->user()->business_id)
->latest()
->get();
$businessId = auth()->user()->business_id;
$transactionsQuery = Transaction::with('paymentType')
->where('business_id', $businessId);
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($transactionsQuery, $duration, 'date', request('from_date'), request('to_date'));
// Search filter
if (request('search')) {
$transactionsQuery->where(function ($query) {
$query->where('amount', 'like', '%' . request('search') . '%')
->orWhere('invoice_no', 'like', '%' . request('search') . '%')
->orWhere('platform', 'like', '%' . request('search') . '%')
->orWhere('type', 'like', '%' . request('search') . '%');
});
}
// Platform filter
if (request('platform')) {
$transactionsQuery->where('platform', request('platform'));
}
// Party Filter
if (request('party_id')) {
$transactionsQuery->where(function ($q) {
$q->where(function ($saleQ) {
$saleQ->where('platform', 'sale')
->whereHas('sale', function ($s) {
$s->where('party_id', request('party_id'));
});
});
$q->where(function ($saleRtnQ) {
$saleRtnQ->where('platform', 'sale_return')
->whereHas('saleReturn.sale', function ($s) {
$s->where('party_id', request('party_id'));
});
});
$q->orWhere(function ($purQ) {
$purQ->where('platform', 'purchase')
->whereHas('purchase', function ($p) {
$p->where('party_id', request('party_id'));
});
});
$q->orWhere(function ($purRtnQ) {
$purRtnQ->where('platform', 'purchase_return')
->whereHas('purchaseReturn.purchase', function ($p) {
$p->where('party_id', request('party_id'));
});
});
$q->orWhere(function ($dueQ) {
$dueQ->where('platform', 'due_collect')
->whereHas('dueCollect', function ($d) {
$d->where('party_id', request('party_id'));
});
});
});
}
$transactions = $transactionsQuery->latest()->limit(request('per_page') ?? 20)->get();
return view('business::transactions.excel-csv', compact('transactions'));
}

View File

@@ -10,8 +10,45 @@ class ExportTransfer implements FromView
{
public function view(): View
{
return view('business::transfers.excel-csv', [
'transfers' => Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])->where('business_id', auth()->user()->business_id)->latest()->get()
]);
$user = auth()->user();
$activeBranchId = $user->active_branch_id;
$transfers = Transfer::with(['fromWarehouse:id,name', 'toWarehouse:id,name', 'toBranch:id,name', 'fromBranch:id,name', 'transferProducts'])
->where('business_id', $user->business_id)
->when($activeBranchId, function ($q) use ($activeBranchId) {
$q->where(function ($query) use ($activeBranchId) {
$query->where('from_branch_id', $activeBranchId)
->orWhere('to_branch_id', $activeBranchId);
});
})
->when(request('branch_id') && !$activeBranchId, function ($q) {
$q->where(function ($query) {
$query->where('from_branch_id', request('branch_id'))->orWhere('to_branch_id', request('branch_id'));
});
})
->when(request('search'), function ($q) {
$search = request('search');
$q->where(function ($q) use ($search) {
$q->where('note', 'like', '%' . $search . '%')
->orWhere('status', 'like', '%' . $search . '%')
->orWhere('invoice_no', 'like', '%' . $search . '%')
->orWhereHas('fromWarehouse', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('toWarehouse', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('toBranch', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('fromBranch', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
});
});
})
->latest()
->limit(request('per_page') ?? 20)->get();
return view('business::transfers.excel-csv', compact('transfers'));
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Modules\Business\App\Exports;
use App\Models\Purchase;
use App\Traits\DateFilterTrait;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
class PurchaseExport implements FromView
{
use DateFilterTrait;
public function view(): View
{
$purchasesQuery = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
$purchasesQuery->when(request('branch_id'), function ($q) {
$q->where('branch_id', request('branch_id'));
});
// Date Filter
$duration = request('custom_days') ?: 'today';
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', request('from_date'), request('to_date'));
// Search Filter
if (request('search')) {
$purchasesQuery->where(function ($query) {
$query->where('paymentType', 'like', '%' . request('search') . '%')
->orWhere('invoiceNumber', 'like', '%' . request('search') . '%')
->orWhereHas('party', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('payment_type', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
})
->orWhereHas('branch', function ($q) {
$q->where('name', 'like', '%' . request('search') . '%');
});
});
}
$purchases = $purchasesQuery->latest()->limit($request->per_page ?? 20)->get();
return view('business::reports.purchase.excel-csv', compact('purchases'));
}
}

View File

@@ -100,28 +100,33 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$businessId = auth()->user()->business_id;
$duration = $request->custom_days ? : 'today';
$fromDate = $request->from_date;
$toDate = $request->to_date;
$perPage = $request->per_page ?? 20;
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
// PRODUCT
$productQuery = Product::select('id', 'business_id', 'productName', 'product_type', 'created_at')
->with(['stocks:id,business_id,product_id,productStock,productPurchasePrice', 'combo_products.stock'])
->where('business_id', $businessId);
$this->applyDateFilter($productQuery, $duration, 'created_at', $fromDate, $toDate);
$products = $productQuery->get()
->map(function ($item) {
$item->source = 'product';
return $item;
});
// BANK
$bankQuery = PaymentType::where('business_id', $businessId);
$this->applyDateFilter($bankQuery, $duration, 'opening_date', $fromDate, $toDate);
$banks = $bankQuery->get()
->map(function ($item) {
$item->source = 'bank';
return $item;
});
$asset_datas = $products->merge($banks);
$asset_datas = $products->merge($banks)->take($perPage);
// TOTAL STOCK VALUE
$total_stock_value = 0;
foreach ($products as $product) {
if (in_array($product->product_type, ['single', 'variant'])) {
@@ -143,6 +148,6 @@ public function exportPdf(Request $request)
$totalBankBalance = $banks->sum('balance');
$total_asset = $total_stock_value + $totalBankBalance;
return PdfService::render('business::balance-sheets.pdf', compact('asset_datas', 'total_asset'),'balance-sheet-report.pdf');
return PdfService::render('business::balance-sheets.pdf', compact('asset_datas', 'total_asset', 'duration', 'filter_from_date', 'filter_to_date'),'balance-sheet-report.pdf');
}
}

View File

@@ -90,13 +90,37 @@ public function exportCsv()
return Excel::download(new ExportBillWisePofit, 'bill-wise-profit.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$profits = Sale::with('party:id,name')
->where('business_id', auth()->user()->business_id)
->latest()
->get();
$salesQuery = Sale::with('party:id,name')
->where('business_id', auth()->user()->business_id);
return PdfService::render('business::bill-wise-profits.pdf', compact('profits'),'bill-wise-profit-report.pdf');
$salesQuery->when($request->search, function ($query) use ($request) {
$query->where(function ($q) use ($request) {
$q->where('lossProfit', 'like', '%' . $request->search . '%')
->orWhere('totalAmount', 'like', '%' . $request->search . '%')
->orWhere('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhereHas('party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
});
$salesQuery->when($request->party_id, function ($query, $partyId) {
if ($partyId === 'Guest') {
$query->whereNull('party_id');
} else {
$query->where('party_id', $partyId);
}
});
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
$profits = $salesQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::bill-wise-profits.pdf', compact('profits', 'duration', 'filter_from_date', 'filter_to_date'),'bill-wise-profit-report.pdf');
}
}

View File

@@ -6,15 +6,21 @@
use App\Models\PaymentType;
use App\Models\Transaction;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use App\Services\PdfService;
use App\Traits\DateFilterTrait;
use App\Traits\DateRangeTrait;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Business\App\Exports\ExportCashBalance;
class AcnooCashController extends Controller
{
use HasUploader;
use DateFilterTrait, DateRangeTrait;
public function index(Request $request)
{
$business_id = auth()->user()->business_id;
@@ -24,37 +30,16 @@ public function index(Request $request)
->where('business_id', auth()->user()->business_id)
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
// Default to today
$startDate = Carbon::today()->format('Y-m-d');
$endDate = Carbon::today()->format('Y-m-d');
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
if ($request->custom_days === 'yesterday') {
$startDate = Carbon::yesterday()->format('Y-m-d');
$endDate = Carbon::yesterday()->format('Y-m-d');
} elseif ($request->custom_days === 'last_seven_days') {
$startDate = Carbon::today()->subDays(6)->format('Y-m-d');
} elseif ($request->custom_days === 'last_thirty_days') {
$startDate = Carbon::today()->subDays(29)->format('Y-m-d');
} elseif ($request->custom_days === 'current_month') {
$startDate = Carbon::now()->startOfMonth()->format('Y-m-d');
$endDate = Carbon::now()->endOfMonth()->format('Y-m-d');
} elseif ($request->custom_days === 'last_month') {
$startDate = Carbon::now()->subMonth()->startOfMonth()->format('Y-m-d');
$endDate = Carbon::now()->subMonth()->endOfMonth()->format('Y-m-d');
} elseif ($request->custom_days === 'current_year') {
$startDate = Carbon::now()->startOfYear()->format('Y-m-d');
$endDate = Carbon::now()->endOfYear()->format('Y-m-d');
} elseif ($request->custom_days === 'custom_date' && $request->from_date && $request->to_date) {
$startDate = Carbon::parse($request->from_date)->format('Y-m-d');
$endDate = Carbon::parse($request->to_date)->format('Y-m-d');
}
$cash->whereDate('date', '>=', $startDate)
->whereDate('date', '<=', $endDate);
$this->applyDateFilter($cash, $duration, 'date', $request->from_date, $request->to_date);
$cashes = $cash->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('date', 'like', '%' . $request->search . '%')
->orWhere('platform', 'like', '%' . $request->search . '%')
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
->orWhere('amount', 'like', '%' . $request->search . '%')
->orWhereHas('user', function ($q) use ($request) {
@@ -65,13 +50,30 @@ public function index(Request $request)
->latest()
->paginate($request->per_page ?? 20)->appends($request->query());
// Sum of all credits and bank_to_cash
$totalCredit = (clone $cash)->where(function ($q) {
$q->where('type', 'credit')
->orWhere('transaction_type', 'bank_to_cash');
})
->sum('amount');
// Sum of all debits and cash_to_bank
$totalDebit = (clone $cash)->where(function ($q) {
$q->where('type', 'debit')
->orWhere('transaction_type', 'cash_to_bank');
})
->sum('amount');
$cash_balance = $totalCredit - $totalDebit;
if ($request->ajax()) {
return response()->json([
'data' => view('business::cashes.datas', compact('cashes'))->render()
'data' => view('business::cashes.datas', compact('cashes', 'cash_balance', 'duration', 'filter_from_date', 'filter_to_date'))->render(),
'cash_balance' => currency_format($cash_balance, 'icon', 2, business_currency())
]);
}
return view('business::cashes.index', compact('cashes', 'banks'));
return view('business::cashes.index', compact('cashes', 'banks', 'cash_balance', 'duration', 'filter_from_date', 'filter_to_date'));
}
public function store(Request $request)
@@ -282,5 +284,109 @@ public function destroy(string $id)
}
}
public function deleteAll(Request $request)
{
$ids = $request->ids;
DB::beginTransaction();
try {
$transactions = Transaction::whereIn('id', $ids)->get();
foreach ($transactions as $transaction) {
// Allow only "cash" platform transactions
if ($transaction->platform !== 'cash') {
return response()->json([
'message' => 'Cannot delete here, please delete from ' . ucfirst($transaction->platform) . ' section.',
], 400);
}
$amount = $transaction->amount;
$toBank = $transaction->to_bank ? PaymentType::find($transaction->to_bank) : null;
switch ($transaction->transaction_type) {
case 'cash_to_bank':
if ($toBank) {
if ($toBank->balance < $amount) {
return response()->json([
'message' => 'Cannot delete: bank balance would go negative.',
], 400);
}
$toBank->decrement('balance', $amount);
}
break;
case 'adjust_cash':
// Cash is static, so no bank adjustments needed
break;
}
if ($transaction->image && file_exists($transaction->image)) {
Storage::delete($transaction->image);
}
$transaction->delete();
}
DB::commit();
return response()->json([
'message' => __('Cash transactions reversed and deleted successfully.'),
'redirect' => route('business.cashes.index'),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'message' => 'Error: ' . $e->getMessage(),
], 500);
}
}
public function exportExcel()
{
return Excel::download(new ExportCashBalance, 'cash-balances.xlsx');
}
public function exportCsv()
{
return Excel::download(new ExportCashBalance, 'cash-balances.csv');
}
public function exportPdf(Request $request)
{
$cash = Transaction::with('user:id,name')
->where('business_id', auth()->user()->business_id)
->whereIn('transaction_type', ['cash_payment', 'bank_to_cash', 'cash_to_bank', 'adjust_cash', 'cheque_to_cash']);
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($cash, $duration, 'date', $request->from_date, $request->to_date);
$cashes = $cash->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('date', 'like', '%' . $request->search . '%')
->orWhere('platform', 'like', '%' . $request->search . '%')
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
->orWhere('amount', 'like', '%' . $request->search . '%')
->orWhereHas('user', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
})
->latest()
->limit($request->per_page ?? 20)->get();
return PdfService::render('business::cashes.pdf', compact('cashes', 'duration', 'filter_from_date', 'filter_to_date'), 'cash-balances.pdf');
}
}

View File

@@ -31,16 +31,6 @@ public function index(Request $request)
->where('business_id', auth()->user()->business_id)
->whereIn('type', ['debit', 'credit']);
$total_cash_in = (clone $query)
->where('type', 'credit')
->sum('amount');
$total_cash_out = (clone $query)
->where('type', 'debit')
->sum('amount');
$total_running_cash = $total_cash_in - $total_cash_out;
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
@@ -70,6 +60,16 @@ public function index(Request $request)
$perPage = $request->input('per_page', 20);
$cash_flows = $query->paginate($perPage)->appends($request->query());
$cashflow_cash_in = (clone $query)
->where('type', 'credit')
->sum('amount');
$cashflow_cash_out = (clone $query)
->where('type', 'debit')
->sum('amount');
$total_running_cash = $cashflow_cash_in - $cashflow_cash_out;
$firstDate = $cash_flows->first()?->date;
if ($firstDate) {
@@ -83,11 +83,14 @@ public function index(Request $request)
if ($request->ajax()) {
return response()->json([
'data' => view('business::cash-flow.datas', compact('cash_flows', 'total_cash_in', 'total_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'))->render()
'data' => view('business::cash-flow.datas', compact('cash_flows', 'cashflow_cash_in', 'cashflow_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
'cashflow_cash_in' => currency_format($cashflow_cash_in, 'icon', 2, business_currency()),
'cashflow_cash_out' => currency_format($cashflow_cash_out, 'icon', 2, business_currency()),
'total_running_cash' => currency_format($total_running_cash, 'icon', 2, business_currency()),
]);
}
return view('business::cash-flow.index', compact('cash_flows', 'total_cash_in', 'total_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'));
return view('business::cash-flow.index', compact('cash_flows', 'cashflow_cash_in', 'cashflow_cash_out', 'opening_balance', 'total_running_cash', 'filter_from_date', 'filter_to_date', 'duration'));
}
public function exportExcel()
@@ -100,9 +103,9 @@ public function exportCsv()
return Excel::download(new ExportCashFlowReport, 'cash-flow.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$cash_flows = Transaction::with([
$query = Transaction::with([
'paymentType:id,name',
'sale:id,party_id',
'sale.party:id,name',
@@ -114,12 +117,47 @@ public function exportPdf()
'dueCollect.party:id,name',
])
->where('business_id', auth()->user()->business_id)
->whereIn('type', ['debit', 'credit'])
->latest()
->get();
->whereIn('type', ['debit', 'credit']);
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($query, $duration, 'date', $request->from_date, $request->to_date);
// Search filter
if ($request->filled('search')) {
$query->where(function ($query) use ($request) {
$query->where('date', 'like', '%' . $request->search . '%')
->orWhere('invoice_no', 'like', '%' . $request->search . '%')
->orWhere('platform', 'like', '%' . $request->search . '%')
->orWhere('amount', 'like', '%' . $request->search . '%')
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
->orWhereHas('paymentType', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
// Platform filter
if ($request->filled('platform')) {
$query->where('platform', $request->platform);
}
// Paginate data
$cash_flows = $query->limit($request->per_page ?? 20)->get();
$firstDate = $cash_flows->first()?->date;
if ($firstDate) {
$opening_balance = (clone $query)
->whereDate('date', '<', $firstDate)
->selectRaw("SUM(CASE WHEN type='credit' THEN amount ELSE 0 END) - SUM(CASE WHEN type='debit' THEN amount ELSE 0 END) as balance")
->value('balance') ?? 0;
} else {
$opening_balance = 0;
}
return PdfService::render('business::cash-flow.pdf', compact('cash_flows', 'opening_balance'),'cash-flow-report.pdf');
return PdfService::render('business::cash-flow.pdf', compact('cash_flows', 'opening_balance', 'duration', 'filter_from_date', 'filter_to_date'),'cash-flow-report.pdf');
}
}

View File

@@ -5,6 +5,7 @@
use App\Models\Product;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Business\App\Exports\ExportComboProduct;
@@ -13,9 +14,14 @@ class AcnooComboProductController extends Controller
public function index(Request $request)
{
$user = auth()->user();
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$search = $request->input('search');
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
->where('business_id', auth()->user()->business_id)
->where('product_type', 'combo')
->withCount('combo_products as total_combo_products')
@@ -31,6 +37,12 @@ public function index(Request $request)
});
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->latest()
->paginate($request->per_page ?? 20)->appends($request->query());
@@ -73,4 +85,55 @@ public function exportCsv()
{
return Excel::download(new ExportComboProduct, 'combo-products.csv');
}
public function exportPdf(Request $request)
{
$user = auth()->user();
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$search = $request->input('search');
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
->where('business_id', auth()->user()->business_id)
->where('product_type', 'combo')
->withCount('combo_products as total_combo_products')
->when($search, function ($q) use ($search) {
$q->where(function ($q) use ($search) {
$q->where('productName', 'like', '%' . $search . '%')
->orWhere('productCode', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('categoryName', 'like', '%' . $search . '%');
})
->orWhereHas('unit', function ($q) use ($search) {
$q->where('unitName', 'like', '%' . $search . '%');
});
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->latest()
->limit($request->per_page ?? 20)->get();
$combo_products->transform(function ($product) {
$product->total_stock = $product->combo_products->sum(function ($combo) {
return optional($combo->stock)->productStock ?? 0;
});
$product->total_cost = $product->combo_products->sum(function ($combo) {
return ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0);
});
return $product;
});
return PdfService::render('business::products.combo-products.pdf', compact('combo_products'),'combo-products.pdf');
}
}

View File

@@ -86,14 +86,41 @@ public function exportCsv()
return Excel::download(new ExportComboProductReport, 'combo-product-report.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$combo_products = Product::with(['combo_products', 'unit:id,unitName', 'category:id,categoryName'])
$user = auth()->user();
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$search = $request->input('search');
$combo_products = Product::with(['combo_products.stock.product', 'unit:id,unitName', 'category:id,categoryName'])
->where('business_id', auth()->user()->business_id)
->where('product_type', 'combo')
->withCount('combo_products as total_combo_products')
->when($search, function ($q) use ($search) {
$q->where(function ($q) use ($search) {
$q->where('productName', 'like', '%' . $search . '%')
->orWhere('productCode', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('categoryName', 'like', '%' . $search . '%');
})
->orWhereHas('unit', function ($q) use ($search) {
$q->where('unitName', 'like', '%' . $search . '%');
});
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('combo_products.stock', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->latest()
->get();
->limit($request->per_page ?? 20)->get();
$combo_products->transform(function ($product) {
$product->total_stock = $product->combo_products->sum(function ($combo) {

View File

@@ -54,7 +54,7 @@ public function index(Request $request)
return view('business::party-reports.customer-ledger.index', compact('customers', 'totalAmount', 'totalPaid', 'totalDue'));
}
public function show(Request $request, $partyId, PartyLedgerService $service)
public function show(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::find($partyId);
$ledger = $service->list($request, $partyId);
@@ -78,18 +78,30 @@ public function exportCsv()
return Excel::download(new ExportCustomerLedger, 'customer-ledger.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$customers = Party::with('sales')
->where('business_id', auth()->user()->business_id)
->where('type', '!=', 'Supplier')
->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%')
->orWhere('phone', 'like', '%' . $request->search . '%')
->orWhere('type', 'like', '%' . $request->search . '%');
});
})
->when(request('type'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('type', $request->type);
});
})
->latest()
->get();
->limit($request->per_page ?? 20)->get();
return PdfService::render('business::party-reports.customer-ledger.pdf', compact('customers'),'customer-ledger-report.pdf');
}
public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService $service)
public function exportLedgerExcel(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::findOrFail($partyId);
@@ -98,7 +110,7 @@ public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService
return Excel::download(new ExportSingleCustomerLedger($ledger, $party), 'single-customer-ledger.xlsx');
}
public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $service)
public function exportLedgerCsv(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::findOrFail($partyId);
@@ -107,15 +119,18 @@ public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $
return Excel::download(new ExportSingleCustomerLedger($ledger, $party), 'single-customer-ledger.csv');
}
public function exportLedgerPdf(Request $request, $partyId, PartyLedgerService $service)
public function exportLedgerPdf(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::findOrFail($partyId);
$ledger = $service->list($request, $partyId);
return PdfService::render(
'business::party-reports.customer-ledger.show-details.pdf',
compact('ledger', 'party'),
$duration = $request->custom_days ?: $request->duration ?: 'today';
[$fromDate, $toDate] = app(PartyLedgerService::class)->applyDateRange($duration, $request->from_date, $request->to_date);
return PdfService::render('business::party-reports.customer-ledger.show-details.pdf',
compact('ledger', 'party', 'duration', 'fromDate', 'toDate'),
strtolower($party->name).'-ledger.pdf'
);
}

View File

@@ -60,44 +60,31 @@ public function index(Request $request)
$query->where('platform', $request->platform);
}
// Calculate summary data
$all_summary_records = (clone $query)->get();
$total_amount = $all_summary_records->sum(function ($day_book) {
return match ($day_book->platform) {
'sale' => $day_book->sale?->totalAmount ?? 0,
'sale_return' => $day_book->saleReturn?->sale?->totalAmount ?? 0,
'purchase' => $day_book->purchase?->totalAmount ?? 0,
'purchase_return' => $day_book->purchaseReturn?->purchase?->totalAmount ?? 0,
'due_collect', 'due_pay' => $day_book->dueCollect?->totalDue ?? 0,
default => 0
};
});
$total_money_in = $all_summary_records->where('type', 'credit')->sum(function ($day_book) {
return match ($day_book->platform) {
'sale' => $day_book->sale?->totalAmount ?? 0,
'sale_return' => $day_book->saleReturn?->sale?->totalAmount ?? 0,
'purchase' => $day_book->purchase?->totalAmount ?? 0,
'purchase_return' => $day_book->purchaseReturn?->purchase?->totalAmount ?? 0,
'due_collect', 'due_pay' => $day_book->dueCollect?->totalDue ?? 0,
default => 0
};
});
$total_money_out = $all_summary_records->where('type', 'debit')->sum('amount');
// Paginate data
$perPage = $request->input('per_page', 20);
$day_books = $query->latest()->paginate($perPage)->appends($request->query());
// Calculate summary data
$total_money_in = (clone $query)
->where('type', 'credit')
->sum('amount');
$total_money_out = (clone $query)
->where('type', 'debit')
->sum('amount');
$total_money_in_out_amount = $total_money_in + $total_money_out;
if ($request->ajax()) {
return response()->json([
'data' => view('business::day-book.datas', compact('day_books', 'total_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'))->render()
'data' => view('business::day-book.datas', compact('day_books', 'total_money_in_out_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
'total_money_in' => currency_format($total_money_in, 'icon', 2, business_currency()),
'total_money_out' => currency_format($total_money_out, 'icon', 2, business_currency()),
'total_money_in_out_amount' => currency_format($total_money_in_out_amount, 'icon', 2, business_currency()),
]);
}
return view('business::day-book.index', compact('day_books', 'total_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'));
return view('business::day-book.index', compact('day_books', 'total_money_in_out_amount', 'total_money_in', 'total_money_out', 'filter_from_date', 'filter_to_date', 'duration'));
}
public function exportExcel()
@@ -110,9 +97,9 @@ public function exportCsv()
return Excel::download(new ExportDayBookReport, 'day-book.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$day_books = Transaction::with([
$query = Transaction::with([
'paymentType:id,name',
'sale:id,user_id,party_id,totalAmount',
'sale.party:id,name',
@@ -127,10 +114,37 @@ public function exportPdf()
'dueCollect.user:id,name',
])
->where('business_id', auth()->user()->business_id)
->whereIn('type', ['debit', 'credit'])
->latest()
->get();
->whereIn('type', ['debit', 'credit']);
return PdfService::render('business::day-book.pdf', compact('day_books'), 'day-book-report.pdf');
// Apply date filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($query, $duration, 'date', $request->from_date, $request->to_date);
// Search filter
if ($request->filled('search')) {
$query->where(function ($query) use ($request) {
$query->where('date', 'like', '%' . $request->search . '%')
->orWhere('invoice_no', 'like', '%' . $request->search . '%')
->orWhere('platform', 'like', '%' . $request->search . '%')
->orWhere('amount', 'like', '%' . $request->search . '%')
->orWhere('type', 'like', '%' . $request->search . '%')
->orWhere('transaction_type', 'like', '%' . $request->search . '%')
->orWhereHas('paymentType', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
// Platform filter
if ($request->filled('platform')) {
$query->where('platform', $request->platform);
}
// Paginate data
$day_books = $query->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::day-book.pdf', compact('day_books', 'duration', 'filter_from_date', 'filter_to_date'),'day-book-report.pdf');
}
}

View File

@@ -13,7 +13,6 @@ class AcnooDiscountProductReportController extends Controller
{
public function index(Request $request)
{
$user = auth()->user();
$branchId = null;
@@ -21,7 +20,7 @@ public function index(Request $request)
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$discount_products = SaleDetails::with('product:id,productName,productCode')
$discount_products = SaleDetails::with('product:id,productName,productCode,hsn_code')
->whereHas('product', function ($q) {
$q->where('business_id', auth()->user()->business_id);
})
@@ -62,13 +61,35 @@ public function exportCsv()
return Excel::download(new ExportDiscountProduct, 'discount-products.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$discount_products = SaleDetails::with('product:id,productName,productCode')
$user = auth()->user();
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
$discount_products = SaleDetails::with('product:id,productName,productCode,hsn_code')
->whereHas('product', function ($q) {
$q->where('business_id', auth()->user()->business_id);
})
->when(request('search'), function ($q) use ($request) {
$q->whereHas('product', function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%')
->orWhere('productCode', 'like', '%' . $request->search . '%')
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
->orWhere('price', 'like', '%' . $request->search . '%')
->orWhere('discount', 'like', '%' . $request->search . '%');
});
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('sale', function ($q) use ($branchId) {
$q->where('branch_id', $branchId);
});
})
->where('discount', '>', 0)
->limit($request->per_page ?? 20)
->get();
return PdfService::render('business::reports.discount-products.pdf', compact('discount_products'),'discount-product-report.pdf');

View File

@@ -2,21 +2,25 @@
namespace Modules\Business\App\Http\Controllers;
use App\Services\Invoice\DueInvoiceService;
use Carbon\Carbon;
use App\Models\Sale;
use App\Models\Party;
use App\Models\Business;
use App\Models\Purchase;
use App\Models\DueCollect;
use App\Models\PaymentType;
use App\Models\Transaction;
use App\Services\PdfService;
use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;
use App\Events\DuePaymentReceived;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Mail;
use App\Events\MultiPaymentProcessed;
use App\Models\Transaction;
use Carbon\Carbon;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Business\App\Exports\ExportDueList;
use Modules\Business\App\Exports\ExportGuestDue;
class AcnooDueController extends Controller
{
@@ -30,29 +34,6 @@ public function index(Request $request)
$businessId = auth()->user()->business_id;
$activeBranch = auth()->user()->active_branch;
if ($activeBranch) {
$total_supplier_due = Party::where('business_id', $businessId)
->where('type', 'Supplier')
->with('purchases_dues')
->get()
->sum(fn($p) => $p->purchases_dues->sum('dueAmount'));
$total_customer_due = Party::where('business_id', $businessId)
->where('type', '!=', 'Supplier')
->with('sales_dues')
->get()
->sum(fn($p) => $p->sales_dues->sum('dueAmount'));
} else {
$total_supplier_due = Party::where('business_id', $businessId)
->where('type', 'Supplier')
->sum('due');
$total_customer_due = Party::where('business_id', $businessId)
->where('type', '!=', 'Supplier')
->sum('due');
}
$query = Party::where('business_id', $businessId)
->with(['purchases_dues', 'sales_dues']);
@@ -75,15 +56,45 @@ public function index(Request $request)
});
}
$totalQuery = clone $query;
$parties = $query->latest()->paginate($request->per_page ?? 20)->appends($request->query());
if ($activeBranch) {
$filtered = $parties->getCollection()
->map(function ($party) {
$total_supplier_due = (clone $totalQuery)
->where('type', 'Supplier')
->get()
->sum(fn ($p) => $p->purchases_dues->sum('dueAmount'));
$party->due = $party->type === 'Supplier'
? $party->purchases_dues->sum('dueAmount')
: $party->sales_dues->sum('dueAmount');
$total_customer_due = (clone $totalQuery)
->where('type', '!=', 'Supplier')
->get()
->sum(fn ($p) => $p->sales_dues->sum('dueAmount'));
} else {
$total_supplier_due = (clone $totalQuery)
->where('type', 'Supplier')
->sum('due');
$total_customer_due = (clone $totalQuery)
->where('type', '!=', 'Supplier')
->sum('due');
}
if ($activeBranch) {
$filtered = $parties->getCollection()
->map(function ($party) use ($activeBranch) {
$sale_dues = $party->type === 'Supplier'
? $party->purchases_dues->where('branch_id', $activeBranch->id)
: $party->sales_dues->where('branch_id', $activeBranch->id);
$party_due = $sale_dues->sum('dueAmount');
if ($party->branch_id === $activeBranch->id) {
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
$party->due = $openingBalanceDue + $party_due;
} else {
$party->due = $party_due;
}
return $party;
})
@@ -100,11 +111,9 @@ public function index(Request $request)
if ($request->ajax()) {
return response()->json([
'data' => view('business::dues.datas', [
'parties' => $parties,
'total_supplier_due' => $total_supplier_due,
'total_customer_due' => $total_customer_due
])->render()
'data' => view('business::dues.datas', compact('parties'))->render(),
'total_supplier_due' => currency_format($total_supplier_due, currency: business_currency()),
'total_customer_due' => currency_format($total_customer_due, currency: business_currency())
]);
}
@@ -115,24 +124,34 @@ public function index(Request $request)
));
}
public function collectDue($id)
public function collectDue(string $id)
{
$activeBranch = auth()->user()->active_branch;
$party = Party::where('business_id', auth()->user()->business_id)->with(['sales_dues', 'purchases_dues'])->findOrFail($id);
$payment_types = PaymentType::where('business_id', auth()->user()->business_id)->whereStatus(1)->latest()->get();
$due_amount = 0;
if ($party->type == 'Supplier') {
foreach ($party->purchases_dues as $sales_due) {
if (! $activeBranch || $sales_due->branch_id === $activeBranch->id) {
$due_amount += $sales_due->dueAmount;
}
}
} else {
foreach ($party->sales_dues as $sales_due) {
if (! $activeBranch || $sales_due->branch_id === $activeBranch->id) {
$due_amount += $sales_due->dueAmount;
}
}
}
if (auth()->user()->active_branch) {
if ($activeBranch) {
if ($party->branch_id === $activeBranch->id && $party->opening_balance_type === 'due') {
$party_opening_due = $party->opening_balance ?? 0;
} else {
$party_opening_due = 0;
}
} else {
$party_opening_due = $party->due - $due_amount;
}
@@ -140,9 +159,11 @@ public function collectDue($id)
return view('business::dues.collect-due', compact('party', 'party_opening_due', 'payment_types'));
}
public function collectDueStore(Request $request)
{
$party = Party::find($request->party_id);
$activeBranch = auth()->user()->active_branch;
$request->validate([
'paymentDate' => 'required|string',
@@ -151,17 +172,11 @@ public function collectDueStore(Request $request)
'invoiceNumber' => 'nullable|exists:'.($party->type == 'Supplier' ? 'purchases' : 'sales').',invoiceNumber',
]);
$business_id = auth()->user()->business_id;
if (auth()->user()->active_branch && !$request->invoiceNumber) {
return response()->json([
'message' => __('You must select an invoice when login any branch.')
], 400);
}
$business = Business::findOrFail(auth()->user()->business_id);
DB::beginTransaction();
try {
$branch_id = null;
$branch_id = $activeBranch?->id;
$invoice = null;
$payments = $request->payments ?? [];
@@ -176,78 +191,101 @@ public function collectDueStore(Request $request)
->reject(fn ($p) => strtolower($p['type']) === 'cheque')
->sum('amount');
// Get related invoice if exists
$invoice_due = 0;
$opening_balance_due = 0;
if ($activeBranch) {
if ($party->type == 'Supplier') {
$invoice_due = Purchase::where('party_id', $request->party_id)
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
} else {
$invoice_due = Sale::where('party_id', $request->party_id)
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
}
if ($party->branch_id === $activeBranch->id && $party->opening_balance_type === 'due') {
$opening_balance_due = $party->opening_balance ?? 0;
}
} else {
if ($party->type == 'Supplier') {
$invoice_due = Purchase::where('party_id', $request->party_id)->sum('dueAmount');
} else {
$invoice_due = Sale::where('party_id', $request->party_id)->sum('dueAmount');
}
$opening_balance_due = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
}
$total_due = $invoice_due + $opening_balance_due;
if ($payDueAmount > $total_due) {
return response()->json([
'message' => __('You can pay maximum '.$total_due.' due amount.'),
], 400);
}
if ($activeBranch && ! $request->invoiceNumber && $invoice_due > 0 && $opening_balance_due == 0) {
return response()->json([
'message' => __('You must select an invoice when login any branch.'),
], 400);
}
if ($request->invoiceNumber) {
if ($party->type == 'Supplier') {
$invoice = Purchase::where('invoiceNumber', $request->invoiceNumber)->where('party_id', $request->party_id)->first();
$invoice = Purchase::where('invoiceNumber', $request->invoiceNumber)
->where('party_id', $request->party_id)
->where('branch_id', $activeBranch?->id)
->first();
} else {
$invoice = Sale::where('invoiceNumber', $request->invoiceNumber)->where('party_id', $request->party_id)->first();
$invoice = Sale::where('invoiceNumber', $request->invoiceNumber)
->where('party_id', $request->party_id)
->where('branch_id', $activeBranch?->id)
->first();
}
if (! isset($invoice)) {
return response()->json([
'message' => 'Invoice Not Found.'
'message' => 'Invoice Not Found.',
], 404);
}
if (!auth()->user()->active_branch) {
if (isset($invoice) && isset($invoice->branch_id)) {
$branch_id = $invoice->branch_id;
}
}
if ($invoice->dueAmount < $request->payDueAmount) {
return response()->json([
'message' => 'Invoice due is ' . $invoice->dueAmount . '. You can not pay more then the invoice due amount.'
], 400);
}
}
// Validation for all invoices due
if (!$request->invoiceNumber) {
if ($party->type == 'Supplier') {
$all_invoice_due = Purchase::where('party_id', $request->party_id)->sum('dueAmount');
} else {
$all_invoice_due = Sale::where('party_id', $request->party_id)->sum('dueAmount');
}
if (($all_invoice_due + $request->payDueAmount) > $party->due) {
return response()->json([
'message' => __('You can pay only ' . $party->due - $all_invoice_due . ', without selecting an invoice.')
'message' => 'Invoice due is '.$invoice->dueAmount.'. You can not pay more then the invoice due amount.',
], 400);
}
if ($party->opening_balance_type == 'due') {
$branch_id = $invoice->branch_id;
}
if (! $request->invoiceNumber && $opening_balance_due > 0) {
$party->update([
'opening_balance' => max(0, $party->opening_balance - $payDueAmount),
]);
}
}
$data = DueCollect::create($request->except('user_id', 'business_id', 'sale_id', 'purchase_id', 'totalDue', 'dueAmountAfterPay', 'paymentDate') + [
'user_id' => auth()->id(),
'business_id' => $business_id,
'sale_id' => $party->type != 'Supplier' && isset($invoice) ? $invoice->id : NULL,
'purchase_id' => $party->type == 'Supplier' && isset($invoice) ? $invoice->id : NULL,
'totalDue' => isset($invoice) ? $invoice->dueAmount : $party->due,
'dueAmountAfterPay'=> isset($invoice) ? ($invoice->dueAmount - $payDueAmount) : ($party->due - $payDueAmount),
'paymentDate' => $request->paymentDate ? Carbon::parse($request->paymentDate)->setTimeFromTimeString(now()->format('H:i:s')) : now()
'business_id' => $business->id,
'sale_id' => $party->type != 'Supplier' && isset($invoice) ? $invoice->id : null,
'purchase_id' => $party->type == 'Supplier' && isset($invoice) ? $invoice->id : null,
'totalDue' => $total_due,
'dueAmountAfterPay' => $total_due - $payDueAmount,
'paymentDate' => $request->paymentDate ? Carbon::parse($request->paymentDate)->setTimeFromTimeString(now()->format('H:i:s')) : now(),
]);
// Update invoice due
if (isset($invoice)) {
$invoice->update([
'dueAmount' => $invoice->dueAmount - $payDueAmount,
'paidAmount' => $invoice->paidAmount + $payDueAmount
'paidAmount' => $invoice->paidAmount + $payDueAmount,
]);
}
// Update party due
$party->update([
'due' => $party->due - $payDueAmount
'due' => $party->due - $payDueAmount,
]);
// update balance & adjust platform
if ($party->type == 'Supplier') {
updateBalance($payDueAmount, 'decrement', $branch_id);
$platform = 'due_pay';
@@ -256,7 +294,6 @@ public function collectDueStore(Request $request)
$platform = 'due_collect';
}
// MultiPaymentProcessed event
event(new MultiPaymentProcessed(
$payments,
$data->id,
@@ -265,45 +302,30 @@ public function collectDueStore(Request $request)
$party->id,
));
// Notify
event(new DuePaymentReceived($data));
sendNotifyToUser($data->id, route('business.dues.index', ['id' => $data->id]), __('Due Collection has been created.'), $business_id);
sendNotifyToUser($data->id, route('business.dues.index', ['id' => $data->id]), __('Due Collection has been created.'), $business->id);
if (moduleCheck('MarketingAddon')) {
$this->dueTransactionMessage($business, $party, $data);
}
DB::commit();
return response()->json([
'message' => __('Collect Due saved successfully'),
'redirect' => route('business.dues.index'),
'secondary_redirect_url' => route('business.collect.dues.invoice', $party->id),
'secondary_redirect_url' => route('business.collect.dues.invoice', $data->id),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json(['message' => $e->getMessage()], 404);
}
}
public function getInvoice($id)
public function getInvoice($party_id, DueInvoiceService $service)
{
$due_collect = DueCollect::with('user:id,name,role', 'party:id,name,email,phone,type', 'payment_type:id,name', 'business:id,companyName,address,phoneNumber,email,vat_name,vat_no,meta', )
->where('business_id', auth()->user()->business_id)
->where('party_id', $id)
->latest()
->first();
$transactionTypes = $due_collect->transactions
->map(function ($transaction) {
if ($transaction->transaction_type === 'bank_payment' && !empty($transaction->paymentType?->name)) {
return $transaction->paymentType->name;
}
return $transaction->transaction_type ? ucfirst(explode('_', $transaction->transaction_type)[0]) : '';
})
->unique()
->implode(', ');
$party = Party::with('dueCollect.business')->find($id);
$bank_detail = PaymentType::where('business_id', auth()->user()->business_id)->where('show_in_invoice', 1)->latest()->first();
return view('business::dues.invoice', compact('due_collect', 'party', 'transactionTypes', 'bank_detail'));
$data = $service->getInvoiceData($party_id);
return view('business::dues.invoice', $data);
}
public function generatePDF($id)
@@ -402,13 +424,22 @@ public function partyDue(Request $request)
$parties = $query->latest()->paginate($request->per_page ?? 20)->appends($request->query());
if ($activeBranch) {
// Calculate branch-wise due and replace $party->due, remove zero-due parties
$parties->setCollection(
$parties->getCollection()
->transform(function ($party) {
$party->due = $party->type === 'Supplier'
? $party->purchases_dues->sum('dueAmount')
: $party->sales_dues->sum('dueAmount');
->transform(function ($party) use ($activeBranch) {
$sale_dues = $party->type === 'Supplier'
? $party->purchases_dues->where('branch_id', $activeBranch->id)
: $party->sales_dues->where('branch_id', $activeBranch->id);
$party_due = $sale_dues->sum('dueAmount');
if ($party->branch_id === $activeBranch->id) {
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
$party->due = $openingBalanceDue + $party_due;
} else {
$party->due = $party_due;
}
return $party;
})
->filter(fn ($party) => $party->due > 0)
@@ -425,13 +456,14 @@ public function partyDue(Request $request)
if ($request->ajax()) {
return response()->json([
'data' => view('business::dues.party.datas', compact('parties'))->render()
'data' => view('business::dues.party.datas', compact('parties'))->render(),
]);
}
return view('business::dues.party.index', compact('parties', 'party_type'));
}
public function walk_dues(Request $request)
{
$walk_in_customers = Sale::where('business_id', auth()->user()->business_id)
@@ -483,8 +515,8 @@ public function walkDuesGetInvoice(string $id)
$due_collect = DueCollect::with('business:id,companyName,address,phoneNumber,email,vat_name,vat_no,meta', 'user:id,name,role', 'payment_type:id,name')
->where('business_id', auth()->user()->business_id)
->whereNull('party_id')
->latest()
->first();
->where('id', $id) // 🔥 FIX HERE
->firstOrFail();
$transactionTypes = $due_collect->transactions
->map(function ($transaction) {
@@ -496,7 +528,8 @@ public function walkDuesGetInvoice(string $id)
->unique()
->implode(', ');
$walk_in_customer = Sale::with('dueCollect.business')->find($id);
// $walk_in_customer = Sale::with('dueCollect.business')->find($id);
$walk_in_customer = Sale::with('dueCollect.business')->find($due_collect->sale_id);
$bank_detail = PaymentType::where('business_id', auth()->user()->business_id)->where('show_in_invoice', 1)->latest()->first();
@@ -527,7 +560,8 @@ public function collectWalkDueStore(Request $request)
DB::beginTransaction();
try {
$branch_id = null;
$invoice = Sale::where('invoiceNumber', $request->invoiceNumber)->whereNull('party_id')->first();
$invoice = Sale::where('business_id', $business_id)->where('invoiceNumber', $request->invoiceNumber)->whereNull('party_id')->first();
if (!$invoice) {
return response()->json([
'message' => 'Invoice Not Found.'
@@ -565,23 +599,23 @@ public function collectWalkDueStore(Request $request)
'sale_id' => $invoice->id,
'invoiceNumber' => $request->invoiceNumber,
'totalDue' => $invoice->dueAmount,
'dueAmountAfterPay' => $invoice->dueAmount - $request->payDueAmount,
'payDueAmount' => $request->payDueAmount,
'dueAmountAfterPay' => $invoice->dueAmount - $payDueAmount,
'payDueAmount' => $payDueAmount,
'paymentDate' => $request->paymentDate,
]);
$invoice->update([
'dueAmount' => $invoice->dueAmount - $request->payDueAmount
'dueAmount' => $invoice->dueAmount - $payDueAmount
]);
updateBalance($request->payDueAmount, 'increment', $branch_id);
updateBalance($payDueAmount, 'increment', $branch_id);
// MultiPaymentProcessed event
event(new MultiPaymentProcessed(
$request->payments ?? [],
$payments,
$data->id,
'due_collect',
$request->payDueAmount,
$payDueAmount,
));
sendNotifyToUser($data->id, route('business.dues.index', ['id' => $data->id]), __('Due Collection has been created.'), $business_id);
@@ -591,7 +625,7 @@ public function collectWalkDueStore(Request $request)
return response()->json([
'message' => __('Collect Due saved successfully'),
'redirect' => route('business.walk-dues.index'),
'secondary_redirect_url' => route('business.collect.walk-dues.invoice', $invoice->id),
'secondary_redirect_url' => route('business.collect.walk-dues.invoice', $data->id),
]);
} catch (\Exception $e) {
DB::rollBack();
@@ -660,4 +694,95 @@ public function viewDuePayment($id)
]);
}
}
public function exportExcel()
{
return Excel::download(new ExportDueList, 'due-list.xlsx');
}
public function exportCsv()
{
return Excel::download(new ExportDueList, 'due-list.csv');
}
public function exportPdf()
{
$businessId = auth()->user()->business_id;
$activeBranch = auth()->user()->active_branch;
$query = Party::where('business_id', $businessId)
->with(['purchases_dues', 'sales_dues']);
if (request('type')) {
$query->where('type', request('type'));
}
if (request('search')) {
$search = request('search');
$query->where(function ($q) use ($search, $activeBranch) {
$q->where('type', 'like', "%$search%")
->orWhere('name', 'like', "%$search%")
->orWhere('phone', 'like', "%$search%")
->orWhere('email', 'like', "%$search%");
if (!$activeBranch) {
$q->orWhere('due', 'like', "%$search%");
}
});
}
$parties = $query->latest()->limit(request('per_page') ?? 20)->get();
if ($activeBranch) {
$parties = $parties->map(function ($party) use ($activeBranch) {
$sale_dues = $party->type === 'Supplier'
? $party->purchases_dues->where('branch_id', $activeBranch->id)
: $party->sales_dues->where('branch_id', $activeBranch->id);
$party_due = $sale_dues->sum('dueAmount');
if ($party->branch_id === $activeBranch->id) {
$openingBalanceDue = $party->opening_balance_type === 'due' ? ($party->opening_balance ?? 0) : 0;
$party->due = $openingBalanceDue + $party_due;
} else {
$party->due = $party_due;
}
return $party;
})->filter(fn($p) => $p->due > 0)->values();
} else {
$parties = $parties->filter(fn($p) => $p->due > 0)->values();
}
return PdfService::render('business::dues.pdf-export', compact('parties'),'due-list.pdf');
}
public function walkDueExportExcel()
{
return Excel::download(new ExportGuestDue, 'guest-due-list.xlsx');
}
public function walkDueExportCsv()
{
return Excel::download(new ExportGuestDue, 'guest-due-list.csv');
}
public function walkDueExportPdf(Request $request)
{
$walk_in_customers = Sale::where('business_id', auth()->user()->business_id)
->with('dueCollect')
->whereNull('party_id')
->where('dueAmount', '>', 0)
->when(request('search'), function ($query) {
$query->where(function ($q) {
$q->where('invoiceNumber', 'like', '%' . request('search') . '%')
->orwhere('dueAmount', 'like', '%' . request('search') . '%');
});
})
->latest()
->limit($request->per_page ?? 20)->get();
return PdfService::render('business::walk-dues.pdf', compact('walk_in_customers'),'guest-due-list.pdf');
}
}

View File

@@ -32,79 +32,56 @@ public function index(Request $request)
->orWhere('credit_limit', 'like', '%' . $request->search . '%');
});
})
->when(request('type'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
->when($request->type, function ($q) use ($request) {
$q->where('type', $request->type);
});
})
->with('sales_dues')
->latest();
if ($activeBranch) {
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
$query->where('due', '>', 0);
}
$parties = $query->paginate($request->per_page ?? 20);
$parties = $query->paginate($request->per_page ?? 20)->appends($request->query());
if ($activeBranch) {
$parties->setCollection(
$parties->getCollection()
->transform(function ($customer) use ($activeBranch) {
$customer->due = $customer->sales_dues
$party_due = $customer->sales_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
if ($customer->branch_id === $activeBranch->id) {
$openingBalanceDue = $customer->opening_balance_type === 'due'
? ($customer->opening_balance ?? 0)
: 0;
$customer->due = $openingBalanceDue + $party_due;
} else {
$customer->due = $party_due;
}
return $customer;
})
->filter(fn($customer) => $customer->due > 0)
->values()
);
} else {
$parties->setCollection(
$parties->getCollection()
->filter(fn($customer) => ($customer->due ?? 0) > 0)
->values()
);
}
$total_due = $parties->sum(fn($customer) => $customer->due);
$customer_total_due = $parties->getCollection()->sum('due');
if ($request->ajax()) {
return response()->json([
'data' => view('business::reports.due.datas', compact('parties', 'total_due'))->render()
'data' => view('business::reports.due.datas', compact('parties'))->render(),
'customer_total_due' => currency_format($customer_total_due, currency: business_currency())
]);
}
if ($activeBranch) {
// Filter customers that have branch-specific due > 0
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
// global due > 0
$query->where('due', '>', 0);
}
$parties = $query->paginate(20)->appends($request->query());
// Replace customer due with branch-specific due if active branch exists
if ($activeBranch) {
$parties->setCollection(
$parties->getCollection()
->transform(function ($customer) use ($activeBranch) {
$customer->due = $customer->sales_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
return $customer;
})
->filter(fn($customer) => $customer->due > 0)
->values()
);
}
// Calculate total_due
$total_due = $parties->sum(fn($customer) => $customer->due);
return view('business::reports.due.due-reports', compact('parties', 'total_due'));
return view('business::reports.due.due-reports', compact('parties', 'customer_total_due'));
}
public function exportExcel()
@@ -117,35 +94,57 @@ public function exportCsv()
return Excel::download(new ExportDue, 'customer-due.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$user = auth()->user();
$businessId = $user->business_id;
$activeBranch = $user->active_branch;
$business_id = $user->business_id;
$query = Party::where('business_id', $businessId)
$query = Party::where('business_id', $business_id)
->where('type', '!=', 'Supplier')
->when($request->search, function ($q) use ($request) {
$q->where(function ($q2) use ($request) {
$q2->where('type', 'like', '%' . $request->search . '%')
->orWhere('name', 'like', '%' . $request->search . '%')
->orWhere('phone', 'like', '%' . $request->search . '%')
->orWhere('credit_limit', 'like', '%' . $request->search . '%');
});
})
->when($request->type, function ($q) use ($request) {
$q->where('type', $request->type);
})
->with('sales_dues')
->latest();
if ($activeBranch) {
$query->whereHas('sales_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
$query->where('due', '>', 0);
}
$parties = $query->get();
if ($activeBranch) {
$parties->transform(function ($supplier) use ($activeBranch) {
$supplier->due = $supplier->sales_dues
$parties = $parties
->transform(function ($customer) use ($activeBranch) {
$party_due = $customer->sales_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
return $supplier;
})->filter(fn($supplier) => $supplier->due > 0);
if ($customer->branch_id === $activeBranch->id) {
$openingBalanceDue = $customer->opening_balance_type === 'due'
? ($customer->opening_balance ?? 0)
: 0;
$customer->due = $openingBalanceDue + $party_due;
} else {
$customer->due = $party_due;
}
return $customer;
})
->filter(fn($customer) => $customer->due > 0)
->take($request->per_page ?? 20)
->values();
} else {
$parties = $parties
->filter(fn($customer) => ($customer->due ?? 0) > 0)
->take($request->per_page ?? 20)
->values();
}
return PdfService::render('business::reports.due.pdf', compact('parties'), 'customer-due-report.pdf');

View File

@@ -0,0 +1,25 @@
<?php
namespace Modules\Business\App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AcnooEstimateController extends Controller
{
public function index(Request $request)
{
return view('business::estimates.index');
}
public function create()
{
return view('business::estimates.create');
}
public function store()
{
return view('business::estimates.create');
}
}

View File

@@ -5,7 +5,6 @@
use App\Models\Branch;
use App\Models\Expense;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use App\Traits\DateFilterTrait;
@@ -26,10 +25,6 @@ public function index(Request $request)
{
$businessId = auth()->user()->business_id;
$total_expense = Expense::where('business_id', $businessId)
->whereDate('expenseDate', Carbon::today()->format('Y-m-d'))
->sum('amount');
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', $businessId);
@@ -90,10 +85,40 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$expense_reports = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
->latest()
->get();
$expenseQuery = Expense::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
return PdfService::render('business::reports.expense.pdf', compact('expense_reports'),'expenses-report.pdf');
$expenseQuery->when($request->branch_id, function ($q) use ($request) {
$q->where('branch_id', $request->branch_id);
});
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
// Search Filter
if ($request->filled('search')) {
$expenseQuery->where(function ($query) use ($request) {
$query->where('expanseFor', 'like', '%' . $request->search . '%')
->orWhere('paymentType', 'like', '%' . $request->search . '%')
->orWhere('referenceNo', 'like', '%' . $request->search . '%')
->orWhere('amount', 'like', '%' . $request->search . '%')
->orWhereHas('category', function ($q) use ($request) {
$q->where('categoryName', 'like', '%' . $request->search . '%');
})
->orWhereHas('payment_type', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
})
->orWhereHas('branch', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
$expense_reports = $expenseQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.expense.pdf', compact('expense_reports', 'duration', 'filter_from_date', 'filter_to_date'),'expenses-report.pdf');
}
}

View File

@@ -5,6 +5,7 @@
use App\Models\Product;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Business\App\Exports\ExportExpiredProduct;
@@ -64,4 +65,38 @@ public function exportCsv()
{
return Excel::download(new ExportExpiredProduct, 'expired-products.csv');
}
public function exportPdf(Request $request)
{
$expired_products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
->where('business_id', auth()->user()->business_id)
->withSum('stocks as total_stock', 'productStock')
->whereHas('stocks', function ($query) {
$query->whereDate('expire_date', '<', today())
->where('productStock', '>', 0);
})
->when($request->search, function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('type', 'like', '%' . $request->search . '%')
->orWhere('productName', 'like', '%' . $request->search . '%')
->orWhere('productCode', 'like', '%' . $request->search . '%')
->orWhere('hsn_code', 'like', '%' . $request->search . '%')
->orWhere('productSalePrice', 'like', '%' . $request->search . '%')
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
->orWhereHas('unit', function ($q) use ($request) {
$q->where('unitName', 'like', '%' . $request->search . '%');
})
->orWhereHas('brand', function ($q) use ($request) {
$q->where('brandName', 'like', '%' . $request->search . '%');
})
->orWhereHas('category', function ($q) use ($request) {
$q->where('categoryName', 'like', '%' . $request->search . '%');
});
});
})
->latest()
->limit($request->per_page ?? 20)->get();
return PdfService::render('business::expired-products.pdf', compact('expired_products'),'expired-products.pdf');
}
}

View File

@@ -80,17 +80,46 @@ public function exportCsv()
return Excel::download(new ExportExpiredProductReport, 'expired-product-reports.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$expired_products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks')
$businessId = auth()->user()->business_id;
$expiredProductsQuery = Product::with(['unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName', 'stocks'])
->withSum('stocks', 'productStock')
->where('business_id', auth()->user()->business_id)
->where('business_id', $businessId)
->whereHas('stocks', function ($query) {
$query->whereDate('expire_date', '<', today())->where('productStock', '>', 0);
})
->latest()
->get();
$query->whereDate('expire_date', '<=', today())->where('productStock', '>', 0);
});
return PdfService::render('business::reports.expired-products.pdf', compact('expired_products'),'expired-product-report.pdf');
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$expiredProductsQuery->whereHas('stocks', function ($q) use ($duration, $request) {
$this->applyDateFilter($q, $duration, 'expire_date', $request->from_date, $request->to_date);
});
// Search Filter
if ($request->filled('search')) {
$search = $request->search;
$expiredProductsQuery->where(function ($query) use ($search) {
$query->where('productName', 'like', '%' . $search . '%')
->orWhere('productCode', 'like', '%' . $search . '%')
->orWhere('productPurchasePrice', 'like', '%' . $search . '%')
->orWhere('productSalePrice', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('categoryName', 'like', '%' . $search . '%');
})
->orWhereHas('brand', function ($q) use ($search) {
$q->where('brandName', 'like', '%' . $search . '%');
})
->orWhereHas('unit', function ($q) use ($search) {
$q->where('unitName', 'like', '%' . $search . '%');
});
});
}
$expired_products = $expiredProductsQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.expired-products.pdf', compact('expired_products', 'duration', 'filter_from_date', 'filter_to_date'),'expired-product-report.pdf');
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Modules\Business\App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\State;
use Illuminate\Http\Request;
class AcnooGetStateController extends Controller
{
public function index(Request $request)
{
$states = State::where('country_id', $request->country_id)->where('status', 1)->orderBy('name')->get(['id', 'name']);
return response()->json([
'status' => true,
'states' => $states
]);
}
}

View File

@@ -83,10 +83,36 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$income_reports = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
->latest()
->get();
$incomeQuery = Income::with('category:id,categoryName', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
return PdfService::render('business::reports.income.pdf', compact('income_reports'),'incomes-report.pdf');
// Branch filter
if ($request->branch_id) {
$incomeQuery->where('branch_id', $request->branch_id);
}
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_date);
// Search filter
if ($request->filled('search')) {
$search = $request->search;
$incomeQuery->where(function ($query) use ($search) {
$query->where('incomeFor', 'like', '%' . $search . '%')
->orWhere('paymentType', 'like', '%' . $search . '%')
->orWhere('amount', 'like', '%' . $search . '%')
->orWhere('referenceNo', 'like', '%' . $search . '%')
->orWhereHas('category', fn($q) => $q->where('categoryName', 'like', '%' . $search . '%'))
->orWhereHas('payment_type', fn($q) => $q->where('name', 'like', '%' . $search . '%'))
->orWhereHas('branch', fn($q) => $q->where('name', 'like', '%' . $search . '%'));
});
}
$income_reports = $incomeQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.income.pdf', compact('income_reports', 'duration', 'filter_from_date', 'filter_to_date'),'incomes-report.pdf');
}
}

View File

@@ -33,14 +33,14 @@ public function lossProfitDetails()
$query->where('business_id', $businessId);
})
->whereDate('created_at', '<', $today)
->sum(DB::raw('productPurchasePrice * productStock'));
->sum(DB::raw('"productPurchasePrice" * "productStock"'));
// Closing stock (up to today) from stocks table
$closing_stock_by_purchase = Stock::whereHas('product', function ($query) use ($businessId) {
$query->where('business_id', $businessId);
})
->whereDate('created_at', '<=', $today)
->sum(DB::raw('productPurchasePrice * productStock'));
->sum(DB::raw('"productPurchasePrice" * "productStock"'));
$total_purchase_price = (clone $purchaseQuery)->sum('totalAmount');
$total_purchase_shipping_charge = (clone $purchaseQuery)->sum('shipping_charge');
@@ -59,13 +59,13 @@ public function lossProfitDetails()
$query->where('business_id', $businessId);
})
->whereDate('created_at', '<', $today)
->sum(DB::raw('productSalePrice * productStock'));
->sum(DB::raw('"productSalePrice" * "productStock"'));
$closing_stock_by_sale = Stock::whereHas('product', function ($query) use ($businessId) {
$query->where('business_id', $businessId);
})
->whereDate('created_at', '<=', $today)
->sum(DB::raw('productSalePrice * productStock'));
->sum(DB::raw('"productSalePrice" * "productStock"'));
$total_sale_price = (clone $salesQuery)->sum('totalAmount');
$total_sale_shipping_charge = (clone $salesQuery)->sum('shipping_charge');
@@ -135,14 +135,14 @@ public function lossProfitFilter(Request $request)
$q->where('business_id', $businessId);
})
->whereDate('created_at', '<', $startDate)
->sum(DB::raw('productPurchasePrice * productStock'));
->sum(DB::raw('"productPurchasePrice" * "productStock"'));
// Closing stock by purchase (up to end date)
$closing_stock_by_purchase = Stock::whereHas('product', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
})
->whereDate('created_at', '<=', $endDate)
->sum(DB::raw('productPurchasePrice * productStock'));
->sum(DB::raw('"productPurchasePrice" * "productStock"'));
$total_purchase_price = (clone $purchaseQuery)->sum('totalAmount');
$total_purchase_shipping_charge = (clone $purchaseQuery)->sum('shipping_charge');
@@ -159,14 +159,14 @@ public function lossProfitFilter(Request $request)
$q->where('business_id', $businessId);
})
->whereDate('created_at', '<', $startDate)
->sum(DB::raw('productSalePrice * productStock'));
->sum(DB::raw('"productSalePrice" * "productStock"'));
// Closing stock by sale
$closing_stock_by_sale = Stock::whereHas('product', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
})
->whereDate('created_at', '<=', $endDate)
->sum(DB::raw('productSalePrice * productStock'));
->sum(DB::raw('"productSalePrice" * "productStock"'));
$total_sale_price = (clone $salesQuery)->sum('totalAmount');
$total_sale_shipping_charge = (clone $salesQuery)->sum('shipping_charge');

View File

@@ -7,17 +7,19 @@
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use App\Traits\DateRangeTrait;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Business\App\Exports\ExportLossProfitHistory;
class AcnooLossProfitHistoryController extends Controller
{
use DateFilterTrait;
use DateFilterTrait, DateRangeTrait;
public function index(Request $request)
{
$user = auth()->user();
$businessId = $user->business_id;
$perPage = request('per_page') ?? 20;
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
@@ -25,42 +27,59 @@ public function index(Request $request)
}
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$salesQuery = DB::table('sales')
->select(
DB::raw('DATE(saleDate) as date'),
DB::raw('"saleDate"::date as date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END as profit_type
"),
DB::raw('SUM(actual_total_amount) as total_sales'),
DB::raw('SUM(lossProfit) as total_sale_income')
DB::raw('SUM("lossProfit") as total_sale_income')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(saleDate)'));
->groupBy(
DB::raw('"saleDate"::date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END
")
);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
$dailySales = $salesQuery->get();
$dailySales = $salesQuery->limit($perPage)->get();
$sale_datas = $dailySales->map(fn ($sale) => (object)[
'type' => 'Sale',
'date' => $sale->date,
'profit_type' => $sale->profit_type,
'total_sales' => $sale->total_sales,
'total_incomes' => $sale->total_sale_income,
]);
$incomeQuery = DB::table('incomes')
->select(
DB::raw('DATE(incomeDate) as date'),
DB::raw('"incomeDate"::date as date'),
DB::raw('SUM(amount) as total_incomes')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(incomeDate)'));
->groupBy(DB::raw('"incomeDate"::date'));
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_date);
$dailyIncomes = $incomeQuery->get();
$dailyIncomes = $incomeQuery->limit($perPage)->get();
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
'type' => 'Income',
@@ -80,7 +99,10 @@ public function index(Request $request)
$mergedIncomeSaleData->push($income);
}
if ($sale = $sale_datas->firstWhere('date', $date)) {
// multiple sale rows handle
$salesOfDate = $sale_datas->where('date', $date);
foreach ($salesOfDate as $sale) {
$mergedIncomeSaleData->push($sale);
}
}
@@ -90,32 +112,32 @@ public function index(Request $request)
if (moduleCheck('HrmAddon')) {
$payrollQuery = DB::table('payrolls')
->select(
DB::raw('DATE(date) as date'),
DB::raw('"date"::date as date'),
DB::raw('SUM(amount) as total_payrolls')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(date)'));
->groupBy(DB::raw('"date"::date'));
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
$dailyPayrolls = $payrollQuery->get();
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
}
$expenseQuery = DB::table('expenses')
->select(
DB::raw('DATE(expenseDate) as date'),
DB::raw('"expenseDate"::date as date'),
DB::raw('SUM(amount) as total_expenses_only')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(expenseDate)'));
->groupBy(DB::raw('"expenseDate"::date'));
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
$dailyExpenses = $expenseQuery->get();
$dailyExpenses = $expenseQuery->limit($perPage)->get();
$mergedExpenseData = collect();
$allExpenseDates = $dailyExpenses->pluck('date')
@@ -148,34 +170,6 @@ public function index(Request $request)
$totalExpenses = $mergedExpenseData->sum('total_expenses');
$netProfit = $grossIncomeProfit - $totalExpenses;
$allTimeSales = DB::table('sales')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('actual_total_amount');
$allTimeIncomes = DB::table('incomes')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('amount');
$allTimePayrolls = moduleCheck('HrmAddon')
? DB::table('payrolls')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('amount')
: 0;
$allTimeExpensesOnly = DB::table('expenses')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('amount');
$allTimeSaleProfit = DB::table('sales')->where('business_id', $businessId)->when($branchId, fn ($q) => $q->where('branch_id', $branchId))->sum('lossProfit');
$cardGrossProfit = $allTimeIncomes + $allTimeSaleProfit;
$totalCardExpenses = $allTimePayrolls + $allTimeExpensesOnly;
$cardNetProfit = $cardGrossProfit - $totalCardExpenses;
return view('business::loss-profit-histories.index', compact(
'mergedIncomeSaleData',
'mergedExpenseData',
@@ -183,9 +177,9 @@ public function index(Request $request)
'grossIncomeProfit',
'totalExpenses',
'netProfit',
'cardGrossProfit',
'totalCardExpenses',
'cardNetProfit'
'duration',
'filter_from_date',
'filter_to_date'
));
}
@@ -199,45 +193,71 @@ public function exportCsv()
return Excel::download(new ExportLossProfitHistory, 'loss-profit-history.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$user = auth()->user();
$businessId = $user->business_id;
$perPage = request('per_page') ?? 20;
$branchId = null;
if (moduleCheck('MultiBranchAddon')) {
$branchId = $user->branch_id ?? $user->active_branch_id;
}
// SALES
$dailySales = DB::table('sales')
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$salesQuery = DB::table('sales')
->select(
DB::raw('DATE(saleDate) as date'),
DB::raw('"saleDate"::date as date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END as profit_type
"),
DB::raw('SUM(actual_total_amount) as total_sales'),
DB::raw('SUM(lossProfit) as total_sale_income')
DB::raw('SUM("lossProfit") as total_sale_income')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(saleDate)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(
DB::raw('"saleDate"::date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END
")
);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
$dailySales = $salesQuery->limit($perPage)->get();
$sale_datas = $dailySales->map(fn ($sale) => (object)[
'type' => 'Sale',
'date' => $sale->date,
'profit_type' => $sale->profit_type,
'total_sales' => $sale->total_sales,
'total_incomes' => $sale->total_sale_income,
]);
// INCOME
$dailyIncomes = DB::table('incomes')
$incomeQuery = DB::table('incomes')
->select(
DB::raw('DATE(incomeDate) as date'),
DB::raw('"incomeDate"::date as date'),
DB::raw('SUM(amount) as total_incomes')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(incomeDate)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('"incomeDate"::date'));
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_date);
$dailyIncomes = $incomeQuery->limit($perPage)->get();
$income_datas = $dailyIncomes->map(fn ($income) => (object)[
'type' => 'Income',
@@ -245,46 +265,66 @@ public function exportPdf()
'total_incomes' => $income->total_incomes,
]);
// MERGE SALE + INCOME
$mergedIncomeSaleData = collect();
$allDates = $dailySales->pluck('date')->merge($dailyIncomes->pluck('date'))->unique()->sort();
$allDates = $dailySales->pluck('date')
->merge($dailyIncomes->pluck('date'))
->unique()
->sort();
foreach ($allDates as $date) {
if ($income = $income_datas->firstWhere('date', $date)) {
$mergedIncomeSaleData->push($income);
}
if ($sale = $sale_datas->firstWhere('date', $date)) {
// multiple sale rows handle
$salesOfDate = $sale_datas->where('date', $date);
foreach ($salesOfDate as $sale) {
$mergedIncomeSaleData->push($sale);
}
}
// PAYROLL
$dailyPayrolls = collect();
if (moduleCheck('HrmAddon')) {
$dailyPayrolls = DB::table('payrolls')
$payrollQuery = DB::table('payrolls')
->select(
DB::raw('DATE(date) as date'),
DB::raw('"date"::date as date'),
DB::raw('SUM(amount) as total_payrolls')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(date)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('"date"::date'));
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
$dailyPayrolls = $payrollQuery->limit($perPage)->get();
}
// EXPENSES
$dailyExpenses = DB::table('expenses')
$expenseQuery = DB::table('expenses')
->select(
DB::raw('DATE(expenseDate) as date'),
DB::raw('"expenseDate"::date as date'),
DB::raw('SUM(amount) as total_expenses_only')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->groupBy(DB::raw('DATE(expenseDate)'))
->get();
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('"expenseDate"::date'));
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
$dailyExpenses = $expenseQuery->limit($perPage)->get();
$mergedExpenseData = collect();
$allExpenseDates = $dailyExpenses->pluck('date')->merge($dailyPayrolls->pluck('date'))->unique()->sort();
$allExpenseDates = $dailyExpenses->pluck('date')
->merge($dailyPayrolls->pluck('date'))
->unique()
->sort();
foreach ($allExpenseDates as $date) {
if ($expense = $dailyExpenses->firstWhere('date', $date)) {
$mergedExpenseData->push((object)[
'type' => 'Expense',
@@ -292,6 +332,7 @@ public function exportPdf()
'total_expenses' => $expense->total_expenses_only,
]);
}
if ($payroll = $dailyPayrolls->firstWhere('date', $date)) {
$mergedExpenseData->push((object)[
'type' => 'Payroll',
@@ -301,9 +342,9 @@ public function exportPdf()
}
}
// SUMMARY
$grossSaleProfit = $sale_datas->sum('total_sales');
$grossIncomeProfit = $income_datas->sum('total_incomes') + $sale_datas->sum('total_incomes');
$totalExpenses = $mergedExpenseData->sum('total_expenses');
$netProfit = $grossIncomeProfit - $totalExpenses;
@@ -316,7 +357,10 @@ public function exportPdf()
'grossSaleProfit',
'grossIncomeProfit',
'totalExpenses',
'netProfit'
'netProfit',
'duration',
'filter_to_date',
'filter_from_date'
),
'loss-profit-history.pdf'
);

View File

@@ -6,10 +6,11 @@
use App\Traits\DateFilterTrait;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Traits\DateRangeTrait;
class AcnooLossProfitHistoryReportController extends Controller
{
use DateFilterTrait;
use DateFilterTrait, DateRangeTrait;
public function index(Request $request)
{
@@ -22,39 +23,56 @@ public function index(Request $request)
}
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$salesQuery = DB::table('sales')
->select(
DB::raw('DATE(saleDate) as date'),
DB::raw('"saleDate"::date as date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END as profit_type
"),
DB::raw('SUM(actual_total_amount) as total_sales'),
DB::raw('SUM(lossProfit) as total_sale_income')
DB::raw('SUM("lossProfit") as total_sale_income')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(saleDate)'));
->groupBy(
DB::raw('"saleDate"::date'),
DB::raw("
CASE
WHEN \"lossProfit\" >= 0 THEN 'positive'
ELSE 'negative'
END
")
);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
$dailySales = $salesQuery->get();
$sale_datas = $dailySales->map(fn ($sale) => (object)[
'type' => 'Sale',
'date' => $sale->date,
'profit_type' => $sale->profit_type,
'total_sales' => $sale->total_sales,
'total_incomes' => $sale->total_sale_income,
]);
$incomeQuery = DB::table('incomes')
->select(
DB::raw('DATE(incomeDate) as date'),
DB::raw('"incomeDate"::date as date'),
DB::raw('SUM(amount) as total_incomes')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(incomeDate)'));
->groupBy(DB::raw('"incomeDate"::date'));
$this->applyDateFilter($incomeQuery, $duration, 'incomeDate', $request->from_date, $request->to_date);
$dailyIncomes = $incomeQuery->get();
@@ -77,7 +95,10 @@ public function index(Request $request)
$mergedIncomeSaleData->push($income);
}
if ($sale = $sale_datas->firstWhere('date', $date)) {
// multiple sale rows handle
$salesOfDate = $sale_datas->where('date', $date);
foreach ($salesOfDate as $sale) {
$mergedIncomeSaleData->push($sale);
}
}
@@ -87,14 +108,14 @@ public function index(Request $request)
if (moduleCheck('HrmAddon')) {
$payrollQuery = DB::table('payrolls')
->select(
DB::raw('DATE(date) as date'),
DB::raw('"date"::date as date'),
DB::raw('SUM(amount) as total_payrolls')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(date)'));
->groupBy(DB::raw('"date"::date'));
$this->applyDateFilter($payrollQuery, $duration, 'date', $request->from_date, $request->to_date);
$dailyPayrolls = $payrollQuery->get();
@@ -102,14 +123,14 @@ public function index(Request $request)
$expenseQuery = DB::table('expenses')
->select(
DB::raw('DATE(expenseDate) as date'),
DB::raw('"expenseDate"::date as date'),
DB::raw('SUM(amount) as total_expenses_only')
)
->where('business_id', $businessId)
->when($branchId, fn ($q) =>
$q->where('branch_id', $branchId)
)
->groupBy(DB::raw('DATE(expenseDate)'));
->groupBy(DB::raw('"expenseDate"::date'));
$this->applyDateFilter($expenseQuery, $duration, 'expenseDate', $request->from_date, $request->to_date);
$dailyExpenses = $expenseQuery->get();
@@ -145,34 +166,6 @@ public function index(Request $request)
$totalExpenses = $mergedExpenseData->sum('total_expenses');
$netProfit = $grossIncomeProfit - $totalExpenses;
$allTimeSales = DB::table('sales')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('actual_total_amount');
$allTimeIncomes = DB::table('incomes')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('amount');
$allTimePayrolls = moduleCheck('HrmAddon')
? DB::table('payrolls')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('amount')
: 0;
$allTimeExpensesOnly = DB::table('expenses')
->where('business_id', $businessId)
->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
->sum('amount');
$allTimeSaleProfit = DB::table('sales')->where('business_id', $businessId)->when($branchId, fn ($q) => $q->where('branch_id', $branchId))->sum('lossProfit');
$cardGrossProfit = $allTimeIncomes + $allTimeSaleProfit;
$totalCardExpenses = $allTimePayrolls + $allTimeExpensesOnly;
$cardNetProfit = $cardGrossProfit - $totalCardExpenses;
return view('business::loss-profit-histories.index', compact(
'mergedIncomeSaleData',
'mergedExpenseData',
@@ -180,9 +173,9 @@ public function index(Request $request)
'grossIncomeProfit',
'totalExpenses',
'netProfit',
'cardGrossProfit',
'totalCardExpenses',
'cardNetProfit'
'duration',
'filter_from_date',
'filter_to_date'
));
}

View File

@@ -3,11 +3,18 @@
namespace Modules\Business\App\Http\Controllers;
use App\Models\Party;
use App\Models\PaymentType;
use App\Helpers\HasUploader;
use App\Imports\PartyImport;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Maatwebsite\Excel\Facades\Excel;
use App\Events\MultiPaymentProcessed;
// use App\Models\Country;
// use App\Models\State;
use Illuminate\Support\Facades\Storage;
class AcnooPartyController extends Controller
{
@@ -54,11 +61,19 @@ public function index(Request $request)
$parties->setCollection(
$parties->getCollection()
->transform(function ($party) use ($activeBranch) {
$party_due = $party->type === 'Supplier'
? $party->purchases_dues->sum('dueAmount')
: $party->sales_dues->sum('dueAmount');
$originalDue = $party->getRawOriginal('due') ?? 0;
$originalOpeningBalance = $party->opening_balance ?? 0;
$party->due = $party->branch_id === $activeBranch->id ? $party_due + $party->due : $party_due;
$party_due = $party->type === 'Supplier'
? $party->purchases_dues->where('branch_id', $activeBranch->id)->sum('dueAmount')
: $party->sales_dues->where('branch_id', $activeBranch->id)->sum('dueAmount');
if ($party->branch_id === $activeBranch->id) {
$openingBalanceDue = $party->opening_balance_type === 'due' ? $originalOpeningBalance : 0;
$party->due = $openingBalanceDue + $party_due;
} else {
$party->due = $party_due;
}
return $party;
})
@@ -67,16 +82,20 @@ public function index(Request $request)
if ($request->ajax()) {
return response()->json([
'data' => view('business::parties.datas', compact('parties'))->render()
'data' => view('business::parties.datas', compact('parties'))->render(),
]);
}
return view('business::parties.index', compact('parties', 'party_type'));
}
public function create()
{
return view('business::parties.create');
$countries = [];
$states = [];
return view('business::parties.create', compact('countries', 'states'));
}
public function store(Request $request)
@@ -88,13 +107,12 @@ public function store(Request $request)
'email' => 'nullable|email',
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
'address' => 'nullable|string|max:255',
'tax_no' => 'nullable|string|max:255',
'due' => 'nullable|numeric|min:0',
'billing_address' => 'nullable|array',
'billing_address.address' => 'nullable|string|max:255',
'billing_address.city' => 'nullable|string|max:255',
'billing_address.state' => 'nullable|string|max:255',
'billing_address.zip_code' => 'nullable|string|max:20',
'billing_address.country' => 'nullable|string|max:255',
'shipping_address' => 'nullable|array',
'shipping_address.address' => 'nullable|string|max:255',
'shipping_address.city' => 'nullable|string|max:255',
@@ -127,7 +145,10 @@ public function store(Request $request)
public function edit($id)
{
$party = Party::where('business_id', auth()->user()->business_id)->findOrFail($id);
return view('business::parties.edit', compact('party'));
$countries = [];
$states = [];
return view('business::parties.edit', compact('party', 'countries', 'states'));
}
public function update(Request $request, $id)
@@ -141,13 +162,12 @@ public function update(Request $request, $id)
'email' => 'nullable|email',
'image' => 'nullable|image|mimes:jpeg,png,jpg,svg',
'address' => 'nullable|string|max:255',
'tax_no' => 'nullable|string|max:255',
'due' => 'nullable|numeric|min:0',
'billing_address' => 'nullable|array',
'billing_address.address' => 'nullable|string|max:255',
'billing_address.city' => 'nullable|string|max:255',
'billing_address.state' => 'nullable|string|max:255',
'billing_address.zip_code' => 'nullable|string|max:20',
'billing_address.country' => 'nullable|string|max:255',
'shipping_address' => 'nullable|array',
'shipping_address.address' => 'nullable|string|max:255',
'shipping_address.city' => 'nullable|string|max:255',
@@ -210,6 +230,79 @@ public function update(Request $request, $id)
]);
}
public function advancePayment(string $id)
{
$party = Party::where('business_id', auth()->user()->business_id)->with(['sales_dues', 'purchases_dues'])->findOrFail($id);
$payment_types = PaymentType::where('business_id', auth()->user()->business_id)->whereStatus(1)->latest()->get();
return view('business::parties.advance-payment', compact('party', 'payment_types'));
}
public function advancePaymentStore(Request $request)
{
$request->validate([
'party_id' => 'required|exists:parties,id',
'amount' => 'required|numeric|min:0.01',
'date' => 'nullable|date',
'note' => 'nullable|string|max:255',
]);
DB::beginTransaction();
try {
$party = Party::findOrFail($request->party_id);
$payments = $request->payments ?? [];
if (isset($payments['main'])) {
$mainPayment = $payments['main'];
$mainPayment['amount'] = $request->amount ?? 0;
$payments = [$mainPayment];
}
// Only count actual received money (exclude cheque)
$payAmount = collect($payments)
->reject(fn($p) => strtolower($p['type'] ?? '') === 'cheque')
->sum(fn($p) => $p['amount'] ?? 0);
if ($payAmount <= 0) {
return response()->json([
'message' => __('No valid payment amount received (cheques are pending).')
], 400);
}
// Determine platform based on party type
$platform = $party->type === 'Supplier' ? 'advance_pay' : 'advance_collect';
$party->increment('wallet', $payAmount);
event(new MultiPaymentProcessed(
$payments,
$party->id,
$platform,
$payAmount,
$party->id,
$request->date ?? now(),
$request->note ?? null
));
DB::commit();
$type = in_array($party->type, ['Retailer', 'Dealer', 'Wholesaler']) ? 'Customer' : ($party->type === 'Supplier' ? 'Supplier' : '');
$message = $type === 'Supplier' ? __('Advance amount paid successfully.') : __('Advance amount collected successfully.');
return response()->json([
'message' => $message,
'redirect' => route('business.parties.index', ['type' => $type])
]);
} catch (\Exception $e) {
DB::rollback();
return response()->json([
'error' => 'Transaction failed: ' . $e->getMessage()
], 500);
}
}
public function destroy($id)
{
$party = Party::findOrFail($id);
@@ -266,4 +359,28 @@ public function deleteAll(Request $request)
]);
}
public function bulkStore(Request $request, $type)
{
$request->validate([
'file' => 'required|file|mimes:xlsx,xls,csv'
]);
$businessId = auth()->user()->business_id;
$import = new PartyImport($businessId);
try {
Excel::import($import, $request->file('file'));
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage(),
], 422);
}
return response()->json([
'success' => true,
'message' => __('Bulk upload successfully.'),
'redirect' => route('business.parties.index', ['type' => $type])
]);
}
}

View File

@@ -5,7 +5,6 @@
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Party;
use App\Models\Sale;
use App\Services\PdfService;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Business\App\Exports\ExportPartyLossProfit;
@@ -14,12 +13,6 @@ class AcnooPartyLossProfitController extends Controller
{
public function index(Request $request)
{
$sale = Sale::where('business_id', auth()->user()->business_id)->whereNotNull('party_id')->get();
$totalAmount = $sale->sum('totalAmount');
$totalProfit = $sale->where('lossProfit', '>', 0)->sum('lossProfit') ?? 0;
$totalLoss = $sale->where('lossProfit', '<', 0)->sum('lossProfit') ?? 0;
$parties = Party::with('sales')
->where('business_id', auth()->user()->business_id)
->where('type', '!=', 'Supplier')
@@ -32,13 +25,20 @@ public function index(Request $request)
->paginate($request->per_page ?? 20)
->appends($request->query());
$totalSaleAmount = $parties->sum(fn($party) => $party->sales?->sum('totalAmount') ?? 0);
$totalProfit = $parties->sum(fn($party) => $party->sales?->where('lossProfit', '>', 0)->sum('lossProfit') ?? 0);
$totalLoss = $parties->sum(fn($party) => $party->sales?->where('lossProfit', '<', 0)->sum('lossProfit') ?? 0);
if ($request->ajax()) {
return response()->json([
'data' => view('business::party-reports.loss-profit.datas', compact('parties'))->render()
'data' => view('business::party-reports.loss-profit.datas', compact('parties', 'totalSaleAmount', 'totalProfit', 'totalLoss'))->render(),
'totalSaleAmount' => currency_format($totalSaleAmount, currency: business_currency()),
'totalProfit' => currency_format($totalProfit, currency: business_currency()),
'totalLoss' => currency_format($totalLoss, currency: business_currency()),
]);
}
return view('business::party-reports.loss-profit.index', compact('parties', 'totalAmount', 'totalProfit', 'totalLoss'));
return view('business::party-reports.loss-profit.index', compact('parties', 'totalSaleAmount', 'totalProfit', 'totalLoss'));
}
public function exportExcel()
@@ -51,18 +51,24 @@ public function exportCsv()
return Excel::download(new ExportPartyLossProfit, 'party-loss-profit.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$parties = Party::with('sales')
->where('business_id', auth()->user()->business_id)
->where('type', '!=', 'Supplier')
->when($request->search, function ($query) use ($request) {
$query->where(function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
})
->latest()
->limit($request->per_page ?? 20)
->get();
return PdfService::render('business::party-reports.loss-profit.pdf', compact('parties'),'party-loss-profit-report.pdf');
}
public function view($id)
public function view(string $id)
{
$party = Party::with('sales.details', 'sales.details.product')
->where('id', $id)

View File

@@ -24,7 +24,6 @@
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Storage;
use Modules\Business\App\Exports\ExportProduct;
use Modules\Business\App\Exports\ExportExpiredProduct;
class AcnooProductController extends Controller
{
@@ -67,6 +66,7 @@ public function index(Request $request)
$q->where(function ($q) use ($search) {
$q->where('productName', 'like', "%{$search}%")
->orWhere('productCode', 'like', "%{$search}%")
->orWhere('hsn_code', 'like', "%{$search}%")
->orWhere('productPurchasePrice', 'like', "%{$search}%")
->orWhere('productSalePrice', 'like', "%{$search}%")
->orWhere('product_type', 'like', "%{$search}%")
@@ -114,7 +114,6 @@ public function index(Request $request)
return view('business::products.index', compact('products'));
}
public function create()
{
$business_id = auth()->user()->business_id;
@@ -122,7 +121,7 @@ public function create()
$brands = Brand::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$units = Unit::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$product_id = (Product::where('business_id', $business_id)->count() ?? 0) + 1;
$vats = Vat::where('business_id', $business_id)->latest()->get();
$vats = Vat::whereStatus(1)->where('business_id', $business_id)->latest()->get();
$code = str_pad($product_id, 4, '0', STR_PAD_LEFT);
$product_models = ProductModel::where('business_id', $business_id)->latest()->get();
$warehouses = Warehouse::where('business_id', $business_id)->latest()->get();
@@ -130,9 +129,10 @@ public function create()
$racks = Rack::where('business_id', $business_id)->latest()->get();
$shelves = Shelf::where('business_id', $business_id)->latest()->get();
$profit_option = Option::where('key', 'business-settings')
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
->get()
->firstWhere('value.business_id', $business_id)['product_profit_option'] ?? '';
->firstWhere('value.business_id', $business_id)
->value['product_profit_option'] ?? '';
return view('business::products.create', compact('categories', 'brands', 'units', 'code', 'vats', 'product_models', 'warehouses', 'racks', 'shelves', 'profit_option', 'variations'));
}
@@ -159,6 +159,7 @@ public function store(Request $request)
return $query->where('business_id', $business_id);
}),
],
'hsn_code' => 'nullable|string|max:255',
'alert_qty' => 'nullable|numeric|min:0',
'size' => 'nullable|string|max:255',
'type' => 'nullable|string|max:255',
@@ -206,13 +207,21 @@ function ($attribute, $value, $fail) use ($request) {
$vat = Vat::find($request->vat_id);
$vat_rate = $vat->rate ?? 0;
$combo_tax_inclusive = $request->productSalePrice ?? 0;
$combo_tax_exclusive = $request->productSalePrice ?? 0;
if ($request->vat_id && $request->product_type === 'combo') {
$combo_tax_inclusive = number_format($combo_tax_exclusive * (1 + ($vat_rate / 100)), 3, '.', '');
}
// Create the product
$product = Product::create($request->only('productName', 'unit_id', 'brand_id', 'vat_id', 'vat_type', 'category_id', 'productCode', 'product_type', 'rack_id', 'shelf_id', 'model_id', 'variation_ids', 'warranty_guarantee_info') + [
$product = Product::create($request->only('productName', 'unit_id', 'brand_id', 'vat_id', 'vat_type', 'category_id', 'productCode', 'hsn_code', 'product_type', 'rack_id', 'shelf_id', 'model_id', 'variation_ids', 'warranty_guarantee_info') + [
'business_id' => $business_id,
'alert_qty' => $request->alert_qty ?? 0,
'is_displayed_in_pos' => $request->has('is_displayed_in_pos') ? 1 : 0,
'has_serial' => $request->product_type == 'combo' ? 0 : ($request->has_serial ?? 0),
'profit_percent' => $request->product_type == 'combo' ? $request->profit_percent ?? 0 : 0,
'productSalePrice' => $request->product_type == 'combo' ? $request->productSalePrice ?? 0 : 0,
'productSalePrice' => $request->product_type == 'combo' ? $combo_tax_inclusive : 0, // inclusive sales price
'price_without_tax' => $request->product_type == 'combo' ? $combo_tax_exclusive : 0,
'productPicture' => $request->productPicture ? $this->upload($request, 'productPicture') : NULL,
]);
@@ -220,18 +229,15 @@ function ($attribute, $value, $fail) use ($request) {
if (in_array($request->product_type, ['single', 'variant']) && !empty($request->stocks)) {
$stockData = [];
foreach ($request->stocks as $stock) {
$base_price = $stock['exclusive_price'] ?? 0;
$purchasePrice = $request->vat_type === 'inclusive'
? $base_price + ($base_price * $vat_rate / 100)
: $base_price;
$stockData[] = [
'business_id' => $business_id,
'product_id' => $product->id,
'exclusive_price' => $stock['exclusive_price'] ?? 0,
'batch_no' => $stock['batch_no'] ?? null,
'warehouse_id' => $stock['warehouse_id'] ?? null,
'productStock' => $stock['productStock'] ?? 0,
'productPurchasePrice' => $purchasePrice,
'productPurchasePrice' => $stock['inclusive_price'] ?? 0, // inclusive purchase price / net cost price
'profit_percent' => $stock['profit_percent'] ?? 0,
'productSalePrice' => $stock['productSalePrice'] ?? 0,
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
@@ -281,16 +287,17 @@ public function edit($id)
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$brands = Brand::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$units = Unit::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$vats = Vat::where('business_id', $business_id)->latest()->get();
$vats = Vat::whereStatus(1)->where('business_id', $business_id)->latest()->get();
$product_models = ProductModel::where('business_id', $business_id)->latest()->get();
$warehouses = Warehouse::where('business_id', $business_id)->latest()->get();
$racks = Rack::where('business_id', $business_id)->latest()->get();
$shelves = Shelf::where('business_id', $business_id)->latest()->get();
$variations = Variation::where('business_id', auth()->user()->business_id)->where('status', 1)->get();
$profit_option = Option::where('key', 'business-settings')
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
->get()
->firstWhere('value.business_id', $business_id)['product_profit_option'] ?? '';
->firstWhere('value.business_id', $business_id)
->value['product_profit_option'] ?? '';
$product = Product::with([
'stocks' => function ($query) {
@@ -334,6 +341,7 @@ public function update(Request $request, $id)
return $query->where('business_id', $business_id);
}),
],
'hsn_code' => 'nullable|string|max:255',
'alert_qty' => 'nullable|numeric|min:0',
'size' => 'nullable|string|max:255',
'type' => 'nullable|string|max:255',
@@ -381,12 +389,21 @@ function ($attribute, $value, $fail) use ($request) {
$vat = Vat::find($request->vat_id);
$vat_rate = $vat->rate ?? 0;
$combo_tax_exclusive = $request->productSalePrice ?? 0;
$combo_tax_inclusive = $request->productSalePrice ?? 0;
if ($request->vat_id && $request->product_type === 'combo') {
$combo_tax_inclusive = number_format($combo_tax_exclusive * (1 + ($vat_rate / 100)), 3, '.', '');
}
// Update product
$product->update($request->except(['productPicture', 'productPurchasePrice', 'productDealerPrice', 'productWholeSalePrice', 'alert_qty', 'stocks', 'vat_amount', 'profit_percent', 'is_displayed_in_pos']) + [
$product->update($request->except(['productPicture', 'productPurchasePrice', 'productDealerPrice', 'productWholeSalePrice', 'alert_qty', 'stocks', 'vat_amount', 'profit_percent', 'productSalePrice', 'price_without_tax']) + [
'business_id' => $business_id,
'alert_qty' => $request->alert_qty ?? 0,
'is_displayed_in_pos' => $request->has('is_displayed_in_pos') ? 1 : 0,
'profit_percent' => $request->profit_percent ?? 0,
'has_serial' => $request->product_type == 'combo' ? 0 : ($request->has_serial ?? 0),
'profit_percent' => $request->product_type == 'combo' ? $request->profit_percent ?? 0 : 0,
'productSalePrice' => $request->product_type == 'combo' ? $combo_tax_inclusive : 0, // inclusive sales price
'price_without_tax' => $request->product_type == 'combo' ? $combo_tax_exclusive : 0,
'productPicture' => $request->productPicture ? $this->upload($request, 'productPicture', $product->productPicture) : $product->productPicture,
]);
@@ -406,22 +423,16 @@ function ($attribute, $value, $fail) use ($request) {
// Insert or Update
foreach ($request->stocks as $stock) {
$stockId = $stock['stock_id'] ?? null;
// Recalculate price
$base_price = $stock['exclusive_price'] ?? 0;
$purchasePrice = $request->vat_type === 'inclusive'
? $base_price + ($base_price * $vat_rate / 100)
: $base_price;
$payload = [
'business_id' => $business_id,
'product_id' => $product->id,
'batch_no' => $stock['batch_no'] ?? null,
'warehouse_id' => $stock['warehouse_id'] ?? null,
'productStock' => $stock['productStock'] ?? 0,
'productPurchasePrice' => $purchasePrice,
'exclusive_price' => $stock['exclusive_price'] ?? 0,
'productPurchasePrice' =>$stock['inclusive_price'] ?? 0,
'profit_percent' => $stock['profit_percent'] ?? 0,
'productSalePrice' => $stock['productSalePrice'] ?? 0,
'productWholeSalePrice' => $stock['productWholeSalePrice'] ?? 0,
@@ -431,7 +442,7 @@ function ($attribute, $value, $fail) use ($request) {
'variation_data' => $stock['variation_data'] ?? null,
'variant_name' => $stock['variant_name'] ?? null,
'branch_id' => auth()->user()->branch_id ?? auth()->user()->active_branch_id,
'serial_numbers' => $request->has_serial ? $stock['serial_numbers'] : null,
'serial_numbers' => $request->has_serial ? $stock['serial_numbers'] ?? null : null,
];
if ($stockId) {
@@ -463,13 +474,12 @@ function ($attribute, $value, $fail) use ($request) {
} catch (\Exception $e) {
DB::rollback();
return response()->json([
'message' => __('Something went wrong.'),
'error' => $e->getMessage(),
'message' => $e->getMessage(),
], 406);
}
}
public function destroy($id)
public function destroy(string $id)
{
$product = Product::findOrFail($id);
if (file_exists($product->productPicture)) {
@@ -501,26 +511,40 @@ public function deleteAll(Request $request)
public function getAllProduct()
{
$isTransfer = request()->is_transfer == 1;
$products = Product::with([
'stocks' => function ($query) {
'stocks' => function ($query) use ($isTransfer) {
$query->where('productStock', '>', 0);
if (!$isTransfer) {
$query->where(function ($q) {
$q->whereNull('serial_numbers')
->orWhereJsonLength('serial_numbers', 0);
});
}
},
'category:id,categoryName',
'unit:id,unitName',
'stocks.warehouse:id,name',
'vat:id,rate'
'stocks.warehouse:id,name'
])
->where('business_id', auth()->user()->business_id)
->withSum('stocks as total_stock', 'productStock')
->withSum(['stocks as total_stock' => function ($query) use ($isTransfer) {
$query->where('productStock', '>', 0);
if (!$isTransfer) {
$query->where(function ($q) {
$q->whereNull('serial_numbers')
->orWhereJsonLength('serial_numbers', 0);
});
}
}], 'productStock')
->having('total_stock', '>', 0)
->latest()
->get()
->where('total_stock', '>', 0)
->values();
->get();
return response()->json($products);
}
public function getByCategory($category_id)
public function getByCategory(string $category_id)
{
$products = Product::where('business_id', auth()->user()->business_id)->where('category_id', $category_id)->get();
return response()->json($products);
@@ -536,14 +560,62 @@ public function exportCsv()
return Excel::download(new ExportProduct, 'product.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$products = Product::with('unit:id,unitName', 'brand:id,brandName', 'category:id,categoryName')
->where('business_id', auth()->user()->business_id)
$user = auth()->user();
$search = $request->input('search');
$products = Product::query()
->where('business_id', $user->business_id)
->with([
'stocks',
'unit:id,unitName',
'brand:id,brandName',
'category:id,categoryName',
'warehouse:id,name',
'rack:id,name',
'shelf:id,name',
'combo_products.stock.product:id,productName'
])
->withSum('stocks as total_stock', 'productStock')
->where(function ($query) {
$query->where('product_type', '!=', 'combo')
->orWhere(function ($q) {
$q->where('product_type', 'combo')
->whereHas('combo_products');
});
})
->when($search, function ($q) use ($search) {
$q->where(function ($q) use ($search) {
$q->where('productName', 'like', "%{$search}%")
->orWhere('productCode', 'like', "%{$search}%")
->orWhere('hsn_code', 'like', "%{$search}%")
->orWhere('productPurchasePrice', 'like', "%{$search}%")
->orWhere('productSalePrice', 'like', "%{$search}%")
->orWhere('product_type', 'like', "%{$search}%")
->orWhereHas('category', fn ($q) => $q->where('categoryName', 'like', "%{$search}%"))
->orWhereHas('brand', fn ($q) => $q->where('brandName', 'like', "%{$search}%"))
->orWhereHas('unit', fn ($q) => $q->where('unitName', 'like', "%{$search}%"));
});
})
->latest()
->limit($request->per_page ?? 20)
->get();
$products = $products->transform(function ($product) {
if ($product->product_type === 'combo') {
$product->total_stock = $product->combo_products->sum(
fn ($combo) => $combo->stock?->productStock ?? 0
);
$product->total_cost = $product->combo_products->sum(
fn ($combo) => ($combo->quantity ?? 0) * ($combo->purchase_price ?? 0)
);
}
return $product;
});
return PdfService::render('business::products.pdf', compact('products'),'product-list.pdf');
}
@@ -561,6 +633,7 @@ public function expiredProduct(Request $request)
$q->where('type', 'like', '%' . $request->search . '%')
->orWhere('productName', 'like', '%' . $request->search . '%')
->orWhere('productCode', 'like', '%' . $request->search . '%')
->orWhere('hsn_code', 'like', '%' . $request->search . '%')
->orWhere('productSalePrice', 'like', '%' . $request->search . '%')
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%')
->orWhereHas('unit', function ($q) use ($request) {
@@ -586,103 +659,23 @@ public function expiredProduct(Request $request)
return view('business::expired-products.index', compact('expired_products'));
}
public function exportExpireProductExcel()
{
return Excel::download(new ExportExpiredProduct, 'expired-product.xlsx');
}
public function exportExpireProductCsv()
{
return Excel::download(new ExportExpiredProduct, 'expired-product.csv');
}
public function show($id)
public function show(string $id)
{
$business_id = auth()->user()->business_id;
$product = Product::with('stocks')->where('business_id', $business_id)->findOrFail($id);
$categories = Category::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$brands = Brand::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$units = Unit::where('business_id', $business_id)->whereStatus(1)->latest()->get();
$vats = Vat::where('business_id', $business_id)->latest()->get();
$vats = Vat::whereStatus(1)->where('business_id', $business_id)->latest()->get();
$profit_option = Option::where('key', 'business-settings')
->where('value', 'LIKE', '%"business_id":%' . $business_id . '%')
->where('value', 'LIKE', '%"business_id":' . $business_id . '%')
->get()
->firstWhere('value.business_id', $business_id)['product_profit_option'] ?? '';
->firstWhere('value.business_id', $business_id)
->value['product_profit_option'] ?? '';
return view('business::products.create-stock', compact('categories', 'brands', 'units', 'product', 'vats', 'profit_option'));
}
public function CreateStock(Request $request, string $id)
{
$product = Product::findOrFail($id);
$business_id = auth()->user()->business_id;
$request->validate([
'vat_id' => 'nullable|exists:vats,id',
'vat_type' => 'nullable|in:inclusive,exclusive',
'productDealerPrice' => 'nullable|numeric|min:0',
'exclusive_price' => 'required|numeric|min:0',
'inclusive_price' => 'required|numeric|min:0',
'profit_percent' => 'nullable|numeric',
'productSalePrice' => 'required|numeric|min:0',
'productWholeSalePrice' => 'nullable|numeric|min:0',
'productStock' => 'required|numeric|min:0',
'expire_date' => 'nullable|date',
'batch_no' => 'nullable|string',
'productCode' => [
'nullable',
'unique:products,productCode,' . $product->id . ',id,business_id,' . $business_id,
],
]);
DB::beginTransaction();
try {
// Calculate purchase price including VAT if applicable
$vat = Vat::find($request->vat_id);
$exclusive_price = $request->exclusive_price ?? 0;
$vat_amount = ($exclusive_price * ($vat->rate ?? 0)) / 100;
// Determine final purchase price based on VAT type
$purchase_price = $request->vat_type === 'exclusive' ? $exclusive_price : $exclusive_price + $vat_amount;
$batchNo = $request->batch_no ?? null;
$stock = Stock::where(['batch_no' => $batchNo, 'product_id' => $product->id])->first();
if ($stock) {
$stock->update($request->except('productStock', 'productPurchasePrice', 'productSalePrice', 'productDealerPrice', 'productWholeSalePrice') + [
'productStock' => $stock->productStock + $request->productStock,
'productPurchasePrice' => $purchase_price,
'productSalePrice' => $request->productSalePrice,
'productDealerPrice' => $request->productDealerPrice ?? 0,
'productWholeSalePrice' => $request->productWholeSalePrice ?? 0,
]);
} else {
Stock::create($request->except('productStock', 'productPurchasePrice', 'productSalePrice', 'productDealerPrice', 'productWholeSalePrice') + [
'product_id' => $product->id,
'branch_id' => auth()->user()->branch_id ?? auth()->user()->active_branch_id,
'business_id' => $business_id,
'productStock' => $request->productStock ?? 0,
'productPurchasePrice' => $purchase_price,
'productSalePrice' => $request->productSalePrice,
'productDealerPrice' => $request->productDealerPrice ?? 0,
'productWholeSalePrice' => $request->productWholeSalePrice ?? 0,
]);
}
DB::commit();
return response()->json([
'message' => __('Data saved successfully.'),
'redirect' => route('business.products.index'),
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'message' => __('Something went wrong.'),
], 406);
}
}
public function getShelf(Request $request)
{
$rack = Rack::with('shelves')->find($request->rack_id);
@@ -698,4 +691,53 @@ public function getProductVariants($product_id)
return response()->json($variant_stocks);
}
public function checkSerial(Request $request)
{
$request->validate([
'product_id' => 'required|exists:products,id',
'serial' => 'required|string'
]);
$exists = Stock::where('business_id', auth()->user()->business_id)
->where('product_id', $request->product_id)
->whereNotNull('serial_numbers')
->whereJsonContains('serial_numbers', $request->serial)
->exists();
return response()->json([
'exists' => $exists
]);
}
public function getProductSerials(Request $request)
{
$request->validate([
'product_id' => 'required|exists:products,id',
'warehouse_id' => 'nullable|exists:warehouses,id',
'batch_no' => 'nullable|string',
]);
$business_id = auth()->user()->business_id;
// Get all serial_numbers from stocks
$serials = Stock::where('business_id', $business_id)
->where('product_id', $request->product_id)
->when($request->filled('batch_no'), function ($q) use ($request) {
$q->where('batch_no', $request->batch_no);
})
->when($request->filled('warehouse_id'), function ($q) use ($request) {
$q->where('warehouse_id', $request->warehouse_id);
})
->whereNotNull('serial_numbers')
->pluck('serial_numbers')
->flatten()
->values();
return response()->json([
'success' => true,
'serials' => $serials
]);
}
}

View File

@@ -18,18 +18,15 @@ public function index(Request $request)
$branchId = $user->branch_id ?? $user->active_branch_id;
$baseQuery = SaleDetails::query()
->whereHas('product', fn ($q) =>
$q->where('business_id', $user->business_id)
)
->whereHas('product', fn ($q) => $q->where('business_id', $user->business_id))
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
$q->whereHas('sale', fn ($q) =>
$q->where('branch_id', $branchId)
);
$q->whereHas('sale', fn ($q) => $q->where('branch_id', $branchId));
})
->when($request->filled('search'), function ($q) use ($request) {
$q->whereHas('product', function ($q) use ($request) {
$q->where('productName', 'like', "%{$request->search}%")
->orWhere('productCode', 'like', "%{$request->search}%");
->orWhere('productCode', 'like', "%{$request->search}%")
->orWhere('hsn_code', 'like', "%{$request->search}%");
});
});
@@ -42,11 +39,11 @@ public function index(Request $request)
->sum('lossProfit');
$product_lossProfits = $baseQuery
->with('product:id,productName,productCode')
->with('product:id,productName,productCode,hsn_code')
->select(
'product_id',
DB::raw('SUM(CASE WHEN lossProfit > 0 THEN lossProfit ELSE 0 END) AS profit'),
DB::raw('SUM(CASE WHEN lossProfit < 0 THEN lossProfit ELSE 0 END) AS loss')
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) AS profit'),
DB::raw('SUM(CASE WHEN "lossProfit" < 0 THEN "lossProfit" ELSE 0 END) AS loss')
)
->groupBy('product_id')
->paginate($request->per_page ?? 20)
@@ -54,17 +51,13 @@ public function index(Request $request)
if ($request->ajax()) {
return response()->json([
'data' => view(
'business::reports.product-loss-profit.datas',
compact('product_lossProfits')
)->render()
'data' => view('business::reports.product-loss-profit.datas', compact('product_lossProfits'))->render(),
'loss' => currency_format($loss, currency: business_currency()),
'profit' => currency_format($profit, currency: business_currency())
]);
}
return view(
'business::reports.product-loss-profit.index',
compact('product_lossProfits', 'profit', 'loss')
);
return view('business::reports.product-loss-profit.index', compact('product_lossProfits', 'profit', 'loss'));
}
@@ -78,25 +71,35 @@ public function exportCsv()
return Excel::download(new ExportProductLossProfit, 'product-lossProfit.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$branchId = moduleCheck('MultiBranchAddon') ? auth()->user()->branch_id ?? auth()->user()->active_branch_id : null;
$user = auth()->user();
$branchId = $user->branch_id ?? $user->active_branch_id;
$product_lossProfits = SaleDetails::with('product:id,productName,productCode')
->whereHas('product', function ($q) {
$q->where('business_id', auth()->user()->business_id);
$baseQuery = SaleDetails::query()
->whereHas('product', fn ($q) =>
$q->where('business_id', $user->business_id)
)
->when(moduleCheck('MultiBranchAddon') && $branchId, function ($q) use ($branchId) {
$q->whereHas('sale', fn ($q) => $q->where('branch_id', $branchId));
})
->when($branchId, function ($q) use ($branchId) {
$q->whereHas('sale', function ($sale) use ($branchId) {
$sale->where('branch_id', $branchId);
->when($request->filled('search'), function ($q) use ($request) {
$q->whereHas('product', function ($q) use ($request) {
$q->where('productName', 'like', "%{$request->search}%")
->orWhere('productCode', 'like', "%{$request->search}%")
->orWhere('hsn_code', 'like', "%{$request->search}%");
});
})
});
$product_lossProfits = $baseQuery
->with('product:id,productName,productCode,hsn_code')
->select(
'product_id',
DB::raw('SUM(CASE WHEN lossProfit > 0 THEN lossProfit ELSE 0 END) as profit'),
DB::raw('SUM(CASE WHEN lossProfit < 0 THEN lossProfit ELSE 0 END) as loss')
DB::raw('SUM(CASE WHEN "lossProfit" > 0 THEN "lossProfit" ELSE 0 END) AS profit'),
DB::raw('SUM(CASE WHEN "lossProfit" < 0 THEN "lossProfit" ELSE 0 END) AS loss')
)
->groupBy('product_id')
->limit($request->per_page ?? 20)
->get();
return PdfService::render('business::reports.product-loss-profit.pdf', compact('product_lossProfits'), 'product-loss-profit-report.pdf');

View File

@@ -51,7 +51,7 @@ public function index(Request $request)
return view('business::product-purchase-history-report.index', compact('products', 'total_purchase_qty', 'total_sale_qty', 'filter_from_date', 'filter_to_date', 'duration'));
}
public function show(Request $request, $id)
public function show(Request $request, string $id)
{
$businessId = auth()->user()->business_id;
$duration = $request->custom_days ?: 'today';
@@ -65,7 +65,7 @@ public function show(Request $request, $id)
->whereHas('purchase', function ($purchase) use ($duration, $request) {
$this->applyDateFilter($purchase, $duration, 'purchaseDate', $request->from_date, $request->to_date);
})
->with('purchase:id,invoiceNumber,purchaseDate')
->with('purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
->select('id', 'purchase_id', 'product_id', 'quantities', 'productPurchasePrice');
$purchaseDetailsQuery->when(filled($request->search), function ($q) use ($request) {
@@ -76,6 +76,9 @@ public function show(Request $request, $id)
->orWhereHas('purchase', function ($q) use ($search) {
$q->where('invoiceNumber', 'like', "%{$search}%")
->orWhere('purchaseDate', 'like', "%{$search}%");
})
->orWhereHas('purchase.party', function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
});
}
@@ -89,8 +92,7 @@ public function show(Request $request, $id)
]);
}
return view(
'business::product-purchase-history-report.details',
return view('business::product-purchase-history-report.details',
compact('product', 'purchaseDetails', 'filter_from_date', 'filter_to_date', 'duration')
);
}
@@ -108,9 +110,20 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$businessId = auth()->user()->business_id;
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
$products = $productQuery->get();
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'purchaseDetails.purchase', 'stocks', 'combo_products'])
->where('business_id', $businessId)
->whereHas('purchaseDetails.purchase', function ($purchase) use ($duration, $request) {
$this->applyDateFilter($purchase, $duration, 'purchaseDate', $request->from_date, $request->to_date);
});
$productQuery->when($request->search, function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%');
});
$products = $productQuery->limit($request->per_page ?? 20)->get();
$total_purchase_qty = $products->sum(function ($product) {
return $product->purchaseDetails->sum('quantities');
@@ -120,31 +133,54 @@ public function exportPdf(Request $request)
return $product->saleDetails->sum('quantities');
});
return PdfService::render('business::product-purchase-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty'), 'product-purchase-history.pdf');
return PdfService::render('business::product-purchase-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty', 'duration', 'filter_from_date', 'filter_to_date'), 'product-purchase-history.pdf');
}
public function exportDetailExcel($id)
public function exportDetailExcel(string $id)
{
return Excel::download(new ExportProductPurchaseHistoryDetailReport($id), 'product-purchase-history-details.xlsx');
}
public function exportDetailCsv($id)
public function exportDetailCsv(string $id)
{
return Excel::download(new ExportProductPurchaseHistoryDetailReport($id), 'product-purchase-history-details.csv');
}
public function exportDetailPdf(Request $request, $id)
public function exportDetailPdf(Request $request, string $id)
{
$businessId = auth()->user()->business_id;
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$product = Product::select('id', 'business_id', 'productName')
->where('business_id', auth()->user()->business_id)
->where('business_id', $businessId)
->findOrFail($id);
$purchaseDetailsQuery = $product->purchaseDetails()
->with('purchase:id,invoiceNumber,purchaseDate')
->whereHas('purchase', function ($purchase) use ($duration, $request) {
$this->applyDateFilter($purchase, $duration, 'purchaseDate', $request->from_date, $request->to_date);
})
->with('purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
->select('id', 'purchase_id', 'product_id', 'quantities', 'productPurchasePrice');
$purchaseDetails = $purchaseDetailsQuery->get();
$purchaseDetailsQuery->when(filled($request->search), function ($q) use ($request) {
$search = $request->search;
$q->where(function ($q) use ($search) {
$q->where('productPurchasePrice', 'like', "%{$search}%")
->orWhere('quantities', 'like', "%{$search}%")
->orWhereHas('purchase', function ($q) use ($search) {
$q->where('invoiceNumber', 'like', "%{$search}%")
->orWhere('purchaseDate', 'like', "%{$search}%");
})
->orWhereHas('purchase.party', function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
});
}
);
return PdfService::render('business::product-purchase-history-report.pdf-detail', compact('product', 'purchaseDetails'), 'product-purchase-history-details.pdf');
$purchaseDetails = $purchaseDetailsQuery->limit($request->per_page ?? 20)->get();
return PdfService::render('business::product-purchase-history-report.pdf-detail', compact('product', 'purchaseDetails', 'duration', 'filter_from_date', 'filter_to_date'), 'product-purchase-history-details.pdf');
}
}

View File

@@ -22,7 +22,16 @@ public function index(Request $request)
$q->where('business_id', auth()->user()->business_id);
});
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$query->whereHas('purchase', function ($q) use ($duration, $request) {
$this->applyDateFilter($q, $duration, 'purchaseDate', $request->from_date, $request->to_date);
});
$query->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->whereHas('product', function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%');
})
@@ -34,13 +43,6 @@ public function index(Request $request)
$q->where('name', 'like', '%' . $request->search . '%');
});
});
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$query->whereHas('purchase', function ($q) use ($duration, $request) {
$this->applyDateFilter($q, $duration, 'purchaseDate', $request->from_date, $request->to_date);
});
$product_purchases = $query->paginate($request->per_page ?? 20)->appends($request->query());
@@ -64,14 +66,38 @@ public function exportCsv()
return Excel::download(new ExportProductPurchaseReport, 'product-purchase.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$product_purchases = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
$query = PurchaseDetails::with('product:id,productName', 'purchase:id,party_id,invoiceNumber,purchaseDate', 'purchase.party:id,name')
->whereHas('purchase', function ($q) {
$q->where('business_id', auth()->user()->business_id);
})
->get();
});
return PdfService::render('business::reports.product-purchase.pdf', compact('product_purchases'),'product-purchase-report.pdf');
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$query->whereHas('purchase', function ($q) use ($duration, $request) {
$this->applyDateFilter($q, $duration, 'purchaseDate', $request->from_date, $request->to_date);
});
$query->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->whereHas('product', function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%');
})
->orWhereHas('purchase', function ($q) use ($request) {
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhere('purchaseDate', 'like', '%' . $request->search . '%');
})
->orWhereHas('purchase.party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
});
$product_purchases = $query->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.product-purchase.pdf', compact('product_purchases', 'duration', 'filter_from_date', 'filter_to_date'), 'product-purchase-report.pdf');
}
}

View File

@@ -57,7 +57,7 @@ public function index(Request $request)
return view('business::product-sale-history-report.index', compact('products', 'total_purchase_qty', 'total_sale_qty', 'total_sale_price', 'filter_from_date', 'filter_to_date', 'duration'));
}
public function show(Request $request, $id)
public function show(Request $request, string $id)
{
$businessId = auth()->user()->business_id;
$duration = $request->custom_days ?: 'today';
@@ -82,6 +82,9 @@ public function show(Request $request, $id)
->orWhereHas('sale', function ($q) use ($search) {
$q->where('invoiceNumber', 'like', "%{$search}%")
->orWhere('saleDate', 'like', "%{$search}%");
})
->orWhereHas('sale.party', function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
});
}
@@ -111,9 +114,20 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$businessId = auth()->user()->business_id;
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$productQuery = Product::with('saleDetails', 'purchaseDetails', 'stocks', 'combo_products')->where('business_id', $businessId);
$products = $productQuery->get();
$productQuery = Product::with(['saleDetails', 'purchaseDetails', 'saleDetails.sale', 'stocks', 'combo_products'])
->where('business_id', $businessId)
->whereHas('saleDetails.sale', function ($sale) use ($duration, $request) {
$this->applyDateFilter($sale, $duration, 'saleDate', $request->from_date, $request->to_date);
});
$productQuery->when($request->search, function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%');
});
$products = $productQuery->limit($request->per_page ?? 20)->get();
$total_single_sale_price = $products->sum(function ($product) {
return $product->saleDetails->sum('price');
@@ -129,31 +143,54 @@ public function exportPdf(Request $request)
return $product->saleDetails->sum('quantities');
});
return PdfService::render('business::product-sale-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty', 'total_sale_price'), 'product-sale-history.pdf');
return PdfService::render('business::product-sale-history-report.pdf', compact('products', 'total_purchase_qty', 'total_sale_qty', 'total_sale_price', 'filter_from_date', 'filter_to_date', 'duration'), 'product-sale-history.pdf');
}
public function exportDetailExcel($id)
public function exportDetailExcel(string $id)
{
return Excel::download(new ExportProductSaleHistoryDetailReport($id), 'product-sale-history-details.xlsx');
}
public function exportDetailCsv($id)
public function exportDetailCsv(string $id)
{
return Excel::download(new ExportProductSaleHistoryDetailReport($id), 'product-sale-history-details.csv');
}
public function exportDetailPdf(Request $request, $id)
public function exportDetailPdf(Request $request, string $id)
{
$businessId = auth()->user()->business_id;
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$product = Product::select('id', 'business_id', 'productName')
->where('business_id', auth()->user()->business_id)
->where('business_id', $businessId)
->findOrFail($id);
$saleDetailsQuery = $product->saleDetails()
->whereHas('sale', function ($sale) use ($duration, $request) {
$this->applyDateFilter($sale, $duration, 'saleDate', $request->from_date, $request->to_date);
})
->with('sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
->select('id', 'sale_id', 'product_id', 'quantities', 'lossprofit', 'price', 'productPurchasePrice');
$saleDetails = $saleDetailsQuery->get();
$saleDetailsQuery->when(filled($request->search), function ($q) use ($request) {
$search = $request->search;
$q->where(function ($q) use ($search) {
$q->where('price', 'like', "%{$search}%")
->orWhere('quantities', 'like', "%{$search}%")
->orWhereHas('sale', function ($q) use ($search) {
$q->where('invoiceNumber', 'like', "%{$search}%")
->orWhere('saleDate', 'like', "%{$search}%");
})
->orWhereHas('sale.party', function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
});
}
);
return PdfService::render('business::product-sale-history-report.pdf-detail', compact('product', 'saleDetails'), 'product-sale-history-details.pdf');
$saleDetails = $saleDetailsQuery->limit($request->per_page ?? 20)->get();
return PdfService::render('business::product-sale-history-report.pdf-detail', compact('product', 'saleDetails', 'duration', 'filter_from_date', 'filter_to_date'), 'product-sale-history-details.pdf');
}
}

View File

@@ -3,7 +3,7 @@
namespace Modules\Business\App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Sale;
use App\Models\SaleDetails;
use App\Services\PdfService;
use App\Traits\DateFilterTrait;
use App\Traits\DateRangeTrait;
@@ -17,26 +17,34 @@ class AcnooProductSaleReportController extends Controller
public function index(Request $request)
{
$query = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
->where('business_id', auth()->user()->business_id);
$query->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhere('saleDate', 'like', '%' . $request->search . '%');
})
->orWhereHas('details.product', function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%');
})
->orWhereHas('party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
->whereHas('sale', function ($q) {
$q->where('business_id', auth()->user()->business_id);
});
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($query, $duration, 'saleDate', $request->from_date, $request->to_date);
$query->whereHas('sale', function ($q) use ($duration, $request) {
$this->applyDateFilter($q, $duration, 'saleDate', $request->from_date, $request->to_date);
});
// Search Filter
$query->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->whereHas('product', function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%');
})
->orWhereHas('sale', function ($q) use ($request) {
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhere('saleDate', 'like', '%' . $request->search . '%');
})
->orWhereHas('sale.party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
});
$product_sales = $query->paginate($request->per_page ?? 20)->appends($request->query());
@@ -59,13 +67,39 @@ public function exportCsv()
return Excel::download(new ExportProductSaleReport, 'product-sales.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$product_sales = Sale::with('details:id,sale_id,product_id,quantities,price', 'details.product:id,productName', 'party:id,name')
->where('business_id', auth()->user()->business_id)
->latest()
->get();
$query = SaleDetails::with('product:id,productName', 'sale:id,party_id,invoiceNumber,saleDate', 'sale.party:id,name')
->whereHas('sale', function ($q) {
$q->where('business_id', auth()->user()->business_id);
});
return PdfService::render('business::reports.product-sale.pdf', compact('product_sales'),'product-sale-report.pdf');
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$query->whereHas('sale', function ($q) use ($duration, $request) {
$this->applyDateFilter($q, $duration, 'saleDate', $request->from_date, $request->to_date);
});
// Search Filter
$query->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->whereHas('product', function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%');
})
->orWhereHas('sale', function ($q) use ($request) {
$q->where('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhere('saleDate', 'like', '%' . $request->search . '%');
})
->orWhereHas('sale.party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
});
$product_sales = $query->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.product-sale.pdf', compact('product_sales', 'duration', 'filter_from_date', 'filter_to_date'), 'product-sale-report.pdf');
}
}

View File

@@ -26,10 +26,6 @@ public function index(Request $request)
{
$businessId = auth()->user()->business_id;
$total_purchase = Purchase::where('business_id', $businessId)
->whereDate('purchaseDate', Carbon::today())
->sum('totalAmount');
$purchasesQuery = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', $businessId);
@@ -89,11 +85,38 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$purchases = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id)
->latest()
->get();
$purchasesQuery = Purchase::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
return PdfService::render('business::reports.purchase.pdf', compact('purchases'), 'purchases-report.pdf');
$purchasesQuery->when($request->branch_id, function ($q) use ($request) {
$q->where('branch_id', $request->branch_id);
});
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', $request->from_date, $request->to_date);
// Search Filter
if ($request->filled('search')) {
$purchasesQuery->where(function ($query) use ($request) {
$query->where('paymentType', 'like', '%' . $request->search . '%')
->orWhere('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhereHas('party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
})
->orWhereHas('payment_type', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
})
->orWhereHas('branch', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
$purchases = $purchasesQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.purchase.pdf', compact('purchases', 'duration', 'filter_from_date', 'filter_to_date'), 'purchases-report.pdf');
}
}

View File

@@ -6,7 +6,6 @@
use App\Models\Purchase;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\PurchaseReturnDetail;
use App\Services\PdfService;
use App\Traits\DateFilterTrait;
use App\Traits\DateRangeTrait;
@@ -26,12 +25,6 @@ public function index(Request $request)
{
$businessId = auth()->user()->business_id;
$total_purchase_return = PurchaseReturnDetail::whereHas('purchaseReturn', function ($query) use ($businessId) {
$query->whereHas('purchase', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
});
})->sum('return_amount');
$purchasesQuery = Purchase::with([
'user:id,name',
'branch:id,name',
@@ -54,7 +47,9 @@ public function index(Request $request)
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($purchasesQuery, $duration, 'purchaseDate', $request->from_date, $request->to_date);
$purchasesQuery->whereHas('purchaseReturns', function ($query) use ($duration, $request) {
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
});
// Search Filter
if ($request->filled('search')) {
@@ -69,17 +64,19 @@ public function index(Request $request)
});
}
// Calculate Total Purchase Return Amount in the Selected Date Range
$total_purchase_return = PurchaseReturnDetail::whereHas('purchaseReturn', function ($query) use ($businessId) {
$query->whereHas('purchase', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
});
})->sum('return_amount');
// Pagination
$perPage = $request->input('per_page', 20);
$purchases = $purchasesQuery->latest()->paginate($perPage)->appends($request->query());
$total_purchase_return = (clone $purchasesQuery)
->with('purchaseReturns.details')
->get()
->sum(function ($sale) {
return $sale->purchaseReturns->sum(function ($return) {
return $return->details->sum('return_amount');
});
});
// Handle AJAX Request
if ($request->ajax()) {
return response()->json([
@@ -105,7 +102,7 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$purchases = Purchase::with([
$purchasesQuery = Purchase::with([
'user:id,name',
'branch:id,name',
'party:id,name,email,phone,type',
@@ -117,10 +114,35 @@ public function exportPdf(Request $request)
}
])
->where('business_id', auth()->user()->business_id)
->whereHas('purchaseReturns')
->latest()
->get();
->whereHas('purchaseReturns');
return PdfService::render('business::reports.purchase-return.pdf', compact('purchases'), 'purchase-return-report.pdf');
$purchasesQuery->when($request->branch_id, function ($q) use ($request) {
$q->where('branch_id', $request->branch_id);
});
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$purchasesQuery->whereHas('purchaseReturns', function ($query) use ($duration, $request) {
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
});
// Search Filter
if ($request->filled('search')) {
$purchasesQuery->where(function ($query) use ($request) {
$query->where('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhereHas('party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
})
->orWhereHas('branch', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
$purchases = $purchasesQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.purchase-return.pdf', compact('purchases', 'duration', 'filter_from_date', 'filter_to_date'), 'purchase-return-report.pdf');
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,6 @@
use App\Models\Sale;
use App\Models\Branch;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use App\Traits\DateFilterTrait;
@@ -26,11 +25,8 @@ public function index(Request $request)
{
$businessId = auth()->user()->business_id;
$total_sale = Sale::where('business_id', $businessId)
->whereDate('saleDate', Carbon::today())
->sum('totalAmount');
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', $businessId);
$salesQuery->when($request->branch_id, function ($q) use ($request) {
$q->where('branch_id', $request->branch_id);
});
@@ -88,10 +84,38 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$sales = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')->where('business_id', auth()->user()->business_id)
->latest()
->get();
$salesQuery = Sale::with('user:id,name', 'party:id,name,email,phone,type', 'payment_type:id,name', 'branch:id,name', 'transactions')
->where('business_id', auth()->user()->business_id);
return PdfService::render('business::reports.sales.pdf', compact('sales'),'sales-report.pdf');
$salesQuery->when($request->branch_id, function ($q) use ($request) {
$q->where('branch_id', $request->branch_id);
});
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
// Search Filter
if ($request->filled('search')) {
$salesQuery->where(function ($query) use ($request) {
$query->where('paymentType', 'like', '%' . $request->search . '%')
->orWhere('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhereHas('party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
})
->orWhereHas('payment_type', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
})
->orWhereHas('branch', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
$sales = $salesQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.sales.pdf', compact('sales', 'duration', 'filter_from_date', 'filter_to_date'),'sales-report.pdf');
}
}

View File

@@ -5,7 +5,6 @@
use App\Models\Sale;
use App\Models\Branch;
use Illuminate\Http\Request;
use App\Models\SaleReturnDetails;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use App\Traits\DateFilterTrait;
@@ -24,12 +23,6 @@ public function __construct()
public function index(Request $request)
{
$total_sale_return = SaleReturnDetails::whereHas('saleReturn', function ($query) {
$query->whereHas('sale', function ($q) {
$q->where('business_id', auth()->user()->business_id);
});
})->sum('return_amount');
$businessId = auth()->user()->business_id;
$salesQuery = Sale::with([
@@ -44,9 +37,7 @@ public function index(Request $request)
->with('branch:id,name');
}
])
->where('business_id', $businessId)
->when($request->branch_id, function ($q) use ($request) {
$q->where('branch_id', $request->branch_id);
})->whereHas('saleReturns');
@@ -55,7 +46,9 @@ public function index(Request $request)
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($salesQuery, $duration, 'saleDate', $request->from_date, $request->to_date);
$salesQuery->whereHas('saleReturns', function ($query) use ($request, $duration) {
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
});
// Search Filter
if ($request->filled('search')) {
@@ -70,15 +63,18 @@ public function index(Request $request)
});
}
$total_sale_return = SaleReturnDetails::whereHas('saleReturn', function ($query) use ($businessId) {
$query->whereHas('sale', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
});
})->sum('return_amount');
$perPage = $request->input('per_page', 20);
$sales = $salesQuery->latest()->paginate($perPage)->appends($request->query());
$total_sale_return = (clone $salesQuery)
->with('saleReturns.details')
->get()
->sum(function ($sale) {
return $sale->saleReturns->sum(function ($return) {
return $return->details->sum('return_amount');
});
});
if ($request->ajax()) {
return response()->json([
'data' => view('business::reports.sales-return.datas', compact('sales', 'filter_from_date', 'filter_to_date', 'duration'))->render(),
@@ -103,7 +99,7 @@ public function exportCsv()
public function exportPdf(Request $request)
{
$sales = Sale::with([
$salesQuery = Sale::with([
'user:id,name',
'party:id,name',
'branch:id,name',
@@ -116,10 +112,33 @@ public function exportPdf(Request $request)
}
])
->where('business_id', auth()->user()->business_id)
->whereHas('saleReturns')
->latest()
->get();
->when($request->branch_id, function ($q) use ($request) {
$q->where('branch_id', $request->branch_id);
})->whereHas('saleReturns');
return PdfService::render('business::reports.sales-return.pdf', compact('sales'), 'sales-return-report.pdf');
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$salesQuery->whereHas('saleReturns', function ($query) use ($duration, $request) {
$this->applyDateFilter($query, $duration, 'return_date', $request->from_date, $request->to_date);
});
// Search Filter
if ($request->filled('search')) {
$salesQuery->where(function ($query) use ($request) {
$query->where('invoiceNumber', 'like', '%' . $request->search . '%')
->orWhereHas('party', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
})
->orWhereHas('branch', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
$sales = $salesQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.sales-return.pdf', compact('sales', 'duration', 'filter_from_date', 'filter_to_date'), 'sales-return-report.pdf');
}
}

View File

@@ -2,10 +2,10 @@
namespace Modules\Business\App\Http\Controllers;
use App\Models\Option;
use Illuminate\Http\Request;
use App\Models\ProductSetting;
use App\Http\Controllers\Controller;
use App\Models\Option;
use App\Models\ProductSetting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Validation\ValidationException;
@@ -21,13 +21,19 @@ public function index()
$currencySettingKey = 'currency_setting_'.$businessId;
$currency_setting = Option::where('key', $currencySettingKey)->first();
return view('business::manage-settings.index', compact('invoice_setting', 'product_setting', 'currency_setting'));
$invoiceImgaeSettingKey = 'invoice_setting_images';
$invoice_setting_image = Option::where('key', $invoiceImgaeSettingKey)->first();
$themesettingkey = 'theme_setting_'.$businessId;
$theme_settings = Option::where('key', $themesettingkey)->first()?->value ?? [];
return view('business::manage-settings.index', compact('invoice_setting', 'theme_settings', 'product_setting', 'currency_setting', 'invoice_setting_image'));
}
public function updateInvoice(Request $request)
{
$request->validate([
'invoice_size' => 'required|string|max:100|in:a4,3_inch_80mm',
'invoice_size' => 'required|string|max:100|in:a4,3_inch_80mm,standard_a4',
]);
$key = 'invoice_setting_'.auth()->user()->business_id;
@@ -45,8 +51,8 @@ public function updateInvoice(Request $request)
public function updateProductSetting(Request $request)
{
$request->validate([
'show_product_price' => 'nullable|boolean',
'show_product_code' => 'nullable|boolean',
'show_hsn_code' => 'nullable|boolean',
'show_product_stock' => 'nullable|boolean',
'show_product_sale_price' => 'nullable|boolean',
'show_product_dealer_price' => 'nullable|boolean',
@@ -174,7 +180,7 @@ public function updateSerial(Request $request)
$modules['show_serial'] = $request->boolean('show_serial') ? '1' : '0';
$setting->update([
'modules' => $modules
'modules' => $modules,
]);
Cache::forget('product_setting_'.$businessId);
@@ -183,4 +189,30 @@ public function updateSerial(Request $request)
'message' => 'Serial setting updated successfully.',
]);
}
public function updateTheme(Request $request)
{
$request->validate([
'primary_color' => 'nullable|string|max:100',
'secondary_color' => 'nullable|string|max:100',
'sidebar_color' => 'nullable|string|max:100',
'accent_color' => 'nullable|string|max:100',
]);
$businessId = auth()->user()->business_id;
$setting = Option::updateOrCreate(
['key' => 'theme_setting_'.$businessId],
['value' => [
'primary_color' => $request->primary_color,
'secondary_color' => $request->secondary_color,
'sidebar_color' => $request->sidebar_color,
'accent_color' => $request->accent_color,
]]
);
Cache::forget('theme_setting_'.$businessId);
return response()->json(__('Theme updated successfully.'));
}
}

View File

@@ -2,13 +2,10 @@
namespace Modules\Business\App\Http\Controllers;
use App\Models\Stock;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Pagination\LengthAwarePaginator;
use Modules\Business\App\Exports\ExportCurrentStock;
class AcnooStockController extends Controller
@@ -25,81 +22,130 @@ public function index()
$search_term = request('search');
$per_page = request('per_page', 20);
// Base query
$query = Product::with('stocks','warehouse:id,name', 'rack:id,name', 'shelf:id,name')->where('product_type', '!=', 'combo')->where('business_id', $businessId);
$query = Product::with('stocks', 'category:id,categoryName')
->where('product_type', '!=', 'combo')
->where('business_id', $businessId);
// For Low Stock view - apply search if search term exists
if ($alert_qty_filter) {
// Apply search filter if search term exists
if ($search_term) {
$query->where(function ($q) use ($search_term) {
$q->where('productName', 'like', '%' . $search_term . '%')
->orWhere('productPurchasePrice', 'like', '%' . $search_term . '%')
->orWhere('productSalePrice', 'like', '%' . $search_term . '%');
->orWhere('productCode', 'like', '%' . $search_term . '%')
->orWhere('hsn_code', 'like', '%' . $search_term . '%')
->orWhereHas('category', function ($q) use ($search_term) {
$q->where('categoryName', 'like', '%' . $search_term . '%');
});
});
}
// Get all products (with search applied if any) then filter for low stock
$allProducts = $query->latest()->get();
$filteredProducts = $allProducts->filter(function ($product) {
$totalStock = $product->stocks->sum('productStock');
return $totalStock <= $product->alert_qty;
});
if ($alert_qty_filter) {
$products = $query
->withSum('stocks as total_stock', 'productStock')
->whereRaw('(SELECT COALESCE(SUM("productStock"),0) FROM stocks WHERE stocks.product_id = products.id) <= products.alert_qty')
->latest()
->paginate($per_page)
->appends(request()->query());
// Manual pagination for filtered collection
$currentPage = request('page', 1);
$products = new LengthAwarePaginator(
$filteredProducts->forPage($currentPage, $per_page),
$filteredProducts->count(),
$per_page,
$currentPage,
['path' => request()->url(), 'query' => request()->query()]
);
$total_stock_qty = $products->sum('total_stock');
// Calculate totals for low stock view
$total_stock_value = $filteredProducts->sum(function ($product) {
$total_stock_value = $products->sum(function ($product) {
return $product->stocks->sum(function ($stock) {
return $stock->productStock * $stock->productPurchasePrice;
});
});
$total_qty = $filteredProducts->sum(function ($product) {
return $product->stocks->sum('productStock');
});
} else {
// For All Stock view - NO search, just regular pagination
$products = $query->latest()->paginate($per_page)->appends(request()->query());
$products = $query
->withSum('stocks as total_stock', 'productStock')
->latest()
->paginate($per_page)
->appends(request()->query());
// Calculate totals for all stock
$total_stock_value = Stock::whereHas('product', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
})->sum(DB::raw('productPurchasePrice * productStock'));
$total_stock_qty = $products->sum('total_stock');
$total_qty = Stock::whereHas('product', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
})->sum('productStock');
$total_stock_value = $products->sum(function ($product) {
return $product->stocks->sum(function ($stock) {
return $stock->productStock * $stock->productPurchasePrice;
});
});
}
// Handle AJAX request
if (request()->ajax()) {
return response()->json([
'data' => view('business::stocks.datas', compact('products', 'total_stock_value', 'total_qty'))->render()
'data' => view('business::stocks.datas', compact('products', 'total_stock_value', 'total_stock_qty'))->render(),
'total_stock_qty' => $total_stock_qty,
'total_stock_value' => currency_format($total_stock_value, currency: business_currency())
]);
}
return view('business::stocks.index', [
'products' => $products,
'total_stock_value' => $total_stock_value,
'total_qty' => $total_qty,
'total_stock_qty' => $total_stock_qty,
]);
}
public function exportExcel()
{
return Excel::download(new ExportCurrentStock, 'current-stock.xlsx');
return Excel::download(new ExportCurrentStock, 'stock-list.xlsx');
}
public function exportCsv()
{
return Excel::download(new ExportCurrentStock, 'current-stock.csv');
return Excel::download(new ExportCurrentStock, 'stock-list.csv');
}
public function exportPdf()
{
$businessId = auth()->user()->business_id;
$alert_qty_filter = request('alert_qty');
$search_term = request('search');
$per_page = request('per_page', 20);
$query = Product::with('stocks', 'category:id,categoryName')
->where('product_type', '!=', 'combo')
->where('business_id', $businessId);
if ($search_term) {
$query->where(function ($q) use ($search_term) {
$q->where('productName', 'like', '%' . $search_term . '%')
->orWhere('productCode', 'like', '%' . $search_term . '%')
->orWhere('hsn_code', 'like', '%' . $search_term . '%')
->orWhereHas('category', function ($q) use ($search_term) {
$q->where('categoryName', 'like', '%' . $search_term . '%');
});
});
}
if ($alert_qty_filter) {
$products = $query
->withSum('stocks as total_stock', 'productStock')
->havingRaw('total_stock <= products.alert_qty')
->latest()
->limit($per_page)
->get();
$total_stock_qty = $products->sum('total_stock');
$total_stock_value = $products->sum(function ($product) {
return $product->stocks->sum(function ($stock) {
return $stock->productStock * $stock->productPurchasePrice;
});
});
} else {
$products = $query
->withSum('stocks as total_stock', 'productStock')
->latest()
->limit($per_page)
->get();
$total_stock_qty = $products->sum('total_stock');
$total_stock_value = $products->sum(function ($product) {
return $product->stocks->sum(function ($stock) {
return $stock->productStock * $stock->productPurchasePrice;
});
});
}
return PdfService::render('business::stocks.pdf', compact('products', 'total_stock_qty', 'total_stock_value'), 'stock-list.pdf');
}
}

View File

@@ -2,10 +2,8 @@
namespace Modules\Business\App\Http\Controllers;
use App\Models\Stock;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use App\Services\PdfService;
use Maatwebsite\Excel\Facades\Excel;
@@ -22,31 +20,42 @@ public function index(Request $request)
{
$businessId = auth()->user()->business_id;
$total_stock_value = Stock::whereHas('product', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
})->sum(DB::raw('productPurchasePrice * productStock'));
$productsQuery = Product::with(['stocks' => function ($q) {
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
}])
->where('business_id', $businessId)
->where('product_type', '!=', 'combo');
$total_qty = Stock::whereHas('product', function ($q) use ($businessId) {
$q->where('business_id', $businessId);
})->sum('productStock');
$stock_reports = Product::with('stocks')
->where('business_id', auth()->user()->business_id)
->where('product_type', '!=', 'combo')
->when($request->search, function ($query) use ($request) {
$query->where(function ($q) use ($request) {
if ($request->search) {
$productsQuery->where(function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%')
->orwhere('productSalePrice', 'like', '%' . $request->search . '%')
->orwhere('productPurchasePrice', 'like', '%' . $request->search . '%');
->orWhereHas('stocks', function ($stock) use ($request) {
$stock->where('productSalePrice', 'like', '%' . $request->search . '%')
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%');
});
})
->withSum('stocks', 'productStock')
});
}
$stock_reports = $productsQuery
->latest()
->paginate($request->per_page ?? 20)->appends($request->query());
->paginate($request->per_page ?? 20)
->appends($request->query());
$total_qty = $stock_reports->getCollection()->sum(function ($product) {
return $product->stocks->sum('productStock');
});
$total_stock_value = $stock_reports->getCollection()->sum(function ($product) {
return $product->stocks->sum(function ($stock) {
return $stock->productStock * $stock->productPurchasePrice;
});
});
if ($request->ajax()) {
return response()->json([
'data' => view('business::reports.stocks.datas', compact('stock_reports'))->render()
'data' => view('business::reports.stocks.datas', compact('stock_reports'))->render(),
'total_stock_value' => currency_format($total_stock_value, currency: business_currency()),
'total_qty' => $total_qty
]);
}
@@ -63,21 +72,29 @@ public function exportCsv()
return Excel::download(new ExportCurrentStockReport, 'current-stock-report.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$query = Product::with('stocks')
$productsQuery = Product::with(['stocks' => function ($q) {
$q->select('id', 'product_id', 'productStock', 'productPurchasePrice', 'productSalePrice');
}])
->where('business_id', auth()->user()->business_id)
->where('product_type', '!=', 'combo');
if (request('alert_qty')) {
$stock_reports = $query->get()->filter(function ($product) {
$totalStock = $product->stocks->sum('productStock');
return $totalStock <= $product->alert_qty;
if ($request->search) {
$productsQuery->where(function ($q) use ($request) {
$q->where('productName', 'like', '%' . $request->search . '%')
->orWhereHas('stocks', function ($stock) use ($request) {
$stock->where('productSalePrice', 'like', '%' . $request->search . '%')
->orWhere('productPurchasePrice', 'like', '%' . $request->search . '%');
});
});
} else {
$stock_reports = $query->latest()->get();
}
$stock_reports = $productsQuery
->latest()
->limit($request->per_page ?? 20)
->get();
return PdfService::render('business::reports.stocks.pdf', compact('stock_reports'), 'stock-report.pdf');
}
}

View File

@@ -72,16 +72,42 @@ public function exportCsv()
return Excel::download(new ExportSubscription, 'subscribers.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$subscribers = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id)
->latest()
->get();
$subscriberQuery = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id);
return PdfService::render('business::reports.subscription-reports.pdf', compact('subscribers'),'subscription-reports.pdf');
// Date Filter
$duration = $request->custom_days ?: 'today';
[$filter_from_date, $filter_to_date] = $this->applyDateRange($duration, $request->from_date, $request->to_date);
$this->applyDateFilter($subscriberQuery, $duration, 'created_at', $request->from_date, $request->to_date);
// Search Filter
if ($request->filled('search')) {
$search = $request->search;
$subscriberQuery->where(function ($query) use ($search) {
$query->where('duration', 'like', '%' . $search . '%')
->orWhereHas('plan', function ($q) use ($search) {
$q->where('subscriptionName', 'like', '%' . $search . '%');
})
->orWhereHas('gateway', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
})
->orWhereHas('business', function ($q) use ($search) {
$q->where('companyName', 'like', '%' . $search . '%')
->orWhereHas('category', function ($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
});
});
});
}
public function getInvoice($invoice_id)
$subscribers = $subscriberQuery->latest()->limit($request->per_page ?? 20)->get();
return PdfService::render('business::reports.subscription-reports.pdf', compact('subscribers', 'duration', 'filter_from_date', 'filter_to_date'),'subscription-reports.pdf');
}
public function getInvoice(string $invoice_id)
{
$subscriber = PlanSubscribe::with(['plan:id,subscriptionName','business:id,companyName,business_category_id,pictureUrl,phoneNumber,email,address,meta','business.category:id,name','gateway:id,name'])->where('business_id', auth()->user()->business_id)->findOrFail($invoice_id);
return view('business::reports.subscription-reports.invoice', compact('subscriber'));

View File

@@ -35,82 +35,52 @@ public function index(Request $request)
->with('purchases_dues')
->latest();
// Branch-aware due filter
if ($activeBranch) {
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
$query->where('due', '>', 0);
}
$parties = $query
->paginate($request->per_page ?? 20)
->appends($request->query());
$parties = $query->paginate($request->per_page ?? 20);
// Replace $supplier->due with branch-specific due if active branch exists
if ($activeBranch) {
$parties->setCollection(
$parties->getCollection()
->transform(function ($supplier) use ($activeBranch) {
$supplier->due = $supplier->purchases_dues
$party_due = $supplier->purchases_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
if ($supplier->branch_id === $activeBranch->id) {
$openingBalanceDue = $supplier->opening_balance_type === 'due'
? ($supplier->opening_balance ?? 0)
: 0;
$supplier->due = $openingBalanceDue + $party_due;
} else {
$supplier->due = $party_due;
}
return $supplier;
})
->filter(fn($supplier) => $supplier->due > 0)
->values()
);
} else {
$parties->setCollection(
$parties->getCollection()
->filter(fn($supplier) => ($supplier->due ?? 0) > 0)
->values()
);
}
// Calculate total_due
$total_due = $parties->sum(function ($supplier) {
return $supplier->due;
});
$supplier_total_due = $parties->getCollection()->sum('due');
if ($request->ajax()) {
return response()->json([
'data' => view('business::reports.supplier-due.datas', compact('parties', 'total_due'))->render()
'data' => view('business::reports.supplier-due.datas', compact('parties'))->render(),
'supplier_total_due' => currency_format($supplier_total_due, currency: business_currency())
]);
}
if ($activeBranch) {
// Filter parties that have branch-specific due > 0
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
$query->where('due', '>', 0);
}
$parties = $query->paginate(20)->appends($request->query());
// Calculate total due
$total_due = $parties->sum(function ($supplier) use ($activeBranch) {
if ($activeBranch) {
return $supplier->purchases_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
}
return $supplier->due;
});
// Replace $supplier->due with branch-specific due if active branch exists
if ($activeBranch) {
$parties->setCollection(
$parties->getCollection()
->transform(function ($supplier) use ($activeBranch) {
$supplier->due = $supplier->purchases_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
return $supplier;
})
->filter(fn($supplier) => $supplier->due > 0)
->values()
);
}
return view('business::reports.supplier-due.due-reports', compact('parties', 'total_due'));
return view('business::reports.supplier-due.due-reports', compact('parties', 'supplier_total_due'));
}
public function exportExcel()
@@ -123,7 +93,7 @@ public function exportCsv()
return Excel::download(new ExportSupplierDue, 'supplier-due.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$user = auth()->user();
$businessId = $user->business_id;
@@ -131,27 +101,46 @@ public function exportPdf()
$query = Party::where('business_id', $businessId)
->where('type', 'Supplier')
->when($request->search, function ($q) use ($request) {
$q->where(function ($q2) use ($request) {
$q2->where('type', 'like', '%' . $request->search . '%')
->orWhere('name', 'like', '%' . $request->search . '%')
->orWhere('phone', 'like', '%' . $request->search . '%')
->orWhere('credit_limit', 'like', '%' . $request->search . '%');
});
})
->with('purchases_dues')
->latest();
if ($activeBranch) {
$query->whereHas('purchases_dues', function ($q) use ($activeBranch) {
$q->where('branch_id', $activeBranch->id)
->where('dueAmount', '>', 0);
});
} else {
$query->where('due', '>', 0);
}
$parties = $query->get();
if ($activeBranch) {
$parties->transform(function ($supplier) use ($activeBranch) {
$supplier->due = $supplier->purchases_dues
$parties = $parties
->transform(function ($supplier) use ($activeBranch) {
$party_due = $supplier->purchases_dues
->where('branch_id', $activeBranch->id)
->sum('dueAmount');
if ($supplier->branch_id === $activeBranch->id) {
$openingBalanceDue = $supplier->opening_balance_type === 'due'
? ($supplier->opening_balance ?? 0)
: 0;
$supplier->due = $openingBalanceDue + $party_due;
} else {
$supplier->due = $party_due;
}
return $supplier;
})->filter(fn($supplier) => $supplier->due > 0);
})
->filter(fn($supplier) => $supplier->due > 0)
->take($request->per_page ?? 20)
->values();
} else {
$parties = $parties
->filter(fn($supplier) => ($supplier->due ?? 0) > 0)
->take($request->per_page ?? 20)
->values();
}
return PdfService::render('business::reports.supplier-due.pdf', compact('parties'), 'supplier-due-report.pdf');

View File

@@ -50,7 +50,7 @@ public function index(Request $request)
}
public function show(Request $request, $partyId, PartyLedgerService $service)
public function show(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::find($partyId);
$ledger = $service->list($request, $partyId);
@@ -74,18 +74,25 @@ public function exportCsv()
return Excel::download(new ExportSupplierLedger, 'supplier-ledger.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$suppliers = Party::with('purchases')
->where('business_id', auth()->user()->business_id)
->where('type', '=', 'Supplier')
->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%')
->orWhere('phone', 'like', '%' . $request->search . '%')
->orWhere('type', 'like', '%' . $request->search . '%');
});
})
->latest()
->get();
->limit($request->per_page ?? 20)->get();
return PdfService::render('business::party-reports.supplier-ledger.pdf', compact('suppliers'),'supplier-ledger-report.pdf');
}
public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService $service)
public function exportLedgerExcel(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::findOrFail($partyId);
$ledger = $service->list($request, $partyId);
@@ -93,7 +100,7 @@ public function exportLedgerExcel(Request $request, $partyId, PartyLedgerService
return Excel::download(new ExportSingleSupplierLedger($ledger, $party), 'single-supplier-ledger.xlsx');
}
public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $service)
public function exportLedgerCsv(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::findOrFail($partyId);
$ledger = $service->list($request, $partyId);
@@ -101,14 +108,18 @@ public function exportLedgerCsv(Request $request, $partyId, PartyLedgerService $
return Excel::download(new ExportSingleSupplierLedger($ledger, $party), 'single-supplier-ledger.csv');
}
public function exportLedgerPdf(Request $request, $partyId, PartyLedgerService $service)
public function exportLedgerPdf(Request $request, string $partyId, PartyLedgerService $service)
{
$party = Party::find($partyId);
$ledger = $service->list($request, $partyId);
$duration = $request->custom_days ?: $request->duration ?: 'today';
[$fromDate, $toDate] = app(PartyLedgerService::class)->applyDateRange($duration, $request->from_date, $request->to_date);
return PdfService::render(
'business::party-reports.supplier-ledger.show-details.pdf',
compact('ledger', 'party'),
compact('ledger', 'party', 'duration', 'fromDate', 'toDate'),
strtolower($party->name).'-supplier.pdf'
);
}

View File

@@ -56,16 +56,29 @@ public function exportCsv()
return Excel::download(new ExportTopCustomer, 'top-customers.csv');
}
public function exportPdf()
public function exportPdf(Request $request)
{
$customers = Party::with('sales')
->where('business_id', auth()->user()->business_id)
->where('type', '!=', 'Supplier')
->whereHas('sales')
->when(request('search'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%')
->orWhere('phone', 'like', '%' . $request->search . '%')
->orWhere('email', 'like', '%' . $request->search . '%')
->orWhere('type', 'like', '%' . $request->search . '%');
});
})
->withCount('sales')
->withSum('sales', 'totalAmount')
->orderByDesc('sales_count')
->orderByDesc('sales_sum_total_amount')
->when(request('type'), function ($q) use ($request) {
$q->where(function ($q) use ($request) {
$q->where('type', $request->type);
});
})
->take(5)
->get();

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