diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml new file mode 100644 index 0000000..cfd7e5d --- /dev/null +++ b/.gitea/workflows/ci-cd.yml @@ -0,0 +1,85 @@ +name: CI/CD - ERP Distribution +on: + pull_request: + branches: + - production + types: + - closed +jobs: + build-and-deploy-backend: + name: Build & Deploy Backend + runs-on: linux + if: github.event.pull_request.merged == true + steps: + - name: Checkout code + run: | + git clone \ + --depth 1 \ + --branch production \ + https://oauth2:${{ secrets.DISTRIBUTION }}@gitea.hexdive.com/New_REP_SYSTEM/ERP_Distribution.git \ + . + - name: Restore + run: dotnet restore Distribution/Distribution.csproj + - name: Publish + run: | + rm -rf /tmp/erpdistribution-deploy + mkdir -p /tmp/erpdistribution-deploy + dotnet publish Distribution/Distribution.csproj \ + -c Release \ + -r linux-x64 \ + --self-contained true \ + -o /tmp/erpdistribution-deploy + - name: Stop service + run: systemctl stop erpdistribution.service + - name: Copy to deploy folder + run: | + mkdir -p /home/distribution/core/publish + rm -rf /home/distribution/core/publish/* + cp -r /tmp/erpdistribution-deploy/* /home/distribution/core/publish/ + - name: Fix ownership and permissions + run: | + chown -R distributionuser:distributionuser /home/distribution/core/publish + find /home/distribution/core/publish -type d -exec chmod 755 {} + + find /home/distribution/core/publish -type f -exec chmod 644 {} + + chmod +x /home/distribution/core/publish/Distribution + - name: Restart service + run: systemctl restart erpdistribution.service + - name: Verify + run: | + systemctl is-active erpdistribution.service && echo "✅ Service running" || echo "❌ Service failed" + + build-and-deploy-frontend: + name: Build & Deploy Frontend + runs-on: linux + if: github.event.pull_request.merged == true + steps: + - name: Checkout code + run: | + git clone \ + --depth 1 \ + --branch production \ + https://oauth2:${{ secrets.DISTRIBUTION_FE }}@gitea.hexdive.com/New_REP_SYSTEM/ERP_Distribution_FE.git \ + . + - name: Build Docker image + run: docker build -t erpdistributionfe:latest . + - name: Stop & remove existing container + run: | + docker stop erpdistributionfe 2>/dev/null || true + docker rm erpdistributionfe 2>/dev/null || true + - name: Start container + run: | + docker run -d \ + --name erpdistributionfe \ + -p 8801:3000 \ + --restart unless-stopped \ + --memory="512m" \ + --cpus="1.0" \ + --cap-drop ALL \ + --security-opt no-new-privileges \ + erpdistributionfe:latest + - name: Remove old images + run: docker image prune -f + - name: Verify + run: | + docker ps --filter name=erpdistributionfe --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" \ + | grep erpdistributionfe && echo "✅ Container running" || echo "❌ Container failed" diff --git a/Distribution/.dotnet/.workloadAdvertisingManifestSentinel10.0.300 b/Distribution/.dotnet/.workloadAdvertisingManifestSentinel10.0.300 new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303.aspNetCertificateSentinel b/Distribution/.dotnet/10.0.303.aspNetCertificateSentinel new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303.dotnetFirstUseSentinel b/Distribution/.dotnet/10.0.303.dotnetFirstUseSentinel new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303.toolpath.sentinel b/Distribution/.dotnet/10.0.303.toolpath.sentinel new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303_IsDockerContainer.dotnetUserLevelCache b/Distribution/.dotnet/10.0.303_IsDockerContainer.dotnetUserLevelCache new file mode 100644 index 0000000..c1f22fb --- /dev/null +++ b/Distribution/.dotnet/10.0.303_IsDockerContainer.dotnetUserLevelCache @@ -0,0 +1 @@ +False \ No newline at end of file diff --git a/Distribution/.dotnet/10.0.303_MachineId.dotnetUserLevelCache b/Distribution/.dotnet/10.0.303_MachineId.dotnetUserLevelCache new file mode 100644 index 0000000..1216177 --- /dev/null +++ b/Distribution/.dotnet/10.0.303_MachineId.dotnetUserLevelCache @@ -0,0 +1 @@ +bf7d0202-9a86-43b3-8323-402073a8c61a \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_3c2c0c4055d6437591042769f431029b.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_3c2c0c4055d6437591042769f431029b.trn new file mode 100644 index 0000000..3cc1bfa --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_3c2c0c4055d6437591042769f431029b.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTyW7bMBD9FYFnUaFIaqFuSeygRpDaiI226I3LKCaikAZFZUHgfy8oO0jTWy8EMeCbecvwHTn5BKhDl4fD8hlcHFGOop1LlNAaE4HLZkeqjrcdF0VZcUoZ+41yZG/hDXWo4VqXWgBmUAPmhlRYsV5jY0CUpDSEVjz1lA8j6t6RtIWBZ6uh8OMPCKP1DnXop3XGv6TZ0hZ68JMpgh9g5cYonU5kFsvt7W69wTdN/X15dXV6OcKYGhTWoA61VUW10AJzISrMdcOx7BuKe6r6UpVNRQScYNZFCE4OxWgePzkYHx1E3dGCsoJgKtAxR0ZGmWgrOcLu7ZCYzDYtUj2fy/O1e0fPEFBH8w9DT+0u9GAvnkY12cFcnM4ox8ek9BD8AUK0MPsySx0GGa132XnS9WDBRZSj9TbbDDL2Pjx9MWt70r/6D/m7NH35CnqKYK795GLCohzdSb23DrLVAnWoLrnhghjMSyUxb3qBJTCJVVUL3ipmakihXnsXrZv8NGYrF+EhzPRRh27kMKZp6212GfTeRtBxCknTrzoBN8GbScfs0/2SFKRghCXQFA9TzO7B2AA6QlK3C9O53z8QWlNCEpUpBHAx28i4z77JcZ8emMZUmgKYkqmGqB6q1rRVqxtT123da15pwspKc65Zr4yQSgmmKae94tDUKEeQws7m/Wr6viW1ajEXjcJcMo6VIBzzsq4kV9JUMiE+fczWQ8KpvjGEEoqFbGvMmWK4ZZRhTihpmGx1XaZV+rDknD1PmdxCcDD8JfnO6uBH38fsvATZFxPuJ5f+bjYvxIt1+HV2e+H1I4QspSWtS2t6Duh4PB7/AAAA//8DAAY6R+UCBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_5d637cd612c34f1d8c78e7f3b2716acb.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5d637cd612c34f1d8c78e7f3b2716acb.trn new file mode 100644 index 0000000..6b90bcc --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5d637cd612c34f1d8c78e7f3b2716acb.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTyU7dMBT9lcjrOHiKHWfHqCJEQYDaqjvHvuFZBPvJcRiE3r9XDg9RuuvOuvI5PsP1GwrmEVCPDrfb0ycIeUY1yn4dMcIkJhpTdUfaXnS90A2VHVdK/UY18hfwinqkhLXUasAcJGDhSIsHPlrsHGhKqCOsFYXT3M+of0PGNw6evIUmzj8gzT4G1KOfPrj4XN42vrFTXFyT4gTnYc4m2CLm5PT24u7qGp8p+f306Oj95gxzIWi8Qz3q2pZZbTUWWrdYWCWwGRXDIxtGOlDVEg3vMB8ypGCmZnYPnxpczAGy7VnDeEMw02hXI2eyKbIHM8Pd67YoWWM6KfN6Ha/H/g09QUI9qz8Cfac7sJM/sPHx0QR3MPrg5w2q0TbFLaTsYY1kdTlNJvsYqv0jx5OHkFGNrm6r68nkMabHLzndvls//w/nl8ZufIDq/AT1SFLhhCYOCzoYLNSosQFu8NBKLbqBOwmltuMYsg9LXObqPGS4T6tK1KMzM82F9Oq2Okx24zPYvKQi/ZcsQHjx+Ti6MiCoRtcpusXm6jNuShrScMILx5K3S65uwPkENkPxdJeWPf0/ECYZKYzHS0oQcnVt8qb6ZuZNueCUay0DcJQPigwjtJ3r2s4qJ2UnRytaSzhtrRCWj4PTZhg0t0ywcRCgZNFd2q3WhQJCmNCK4lGqFgupKDbcScwJjAoYpa4riM9Yq6up4IZROcIIw9p0Egs+cNxxxrEgjChuOitp2Z2PSPaNiw7V6AJSgOkvy5fepjjHMVf76qsvIdwsoXzWal2DZx/wyxr+SbQPkKpSnvGh7OW+r91ut/sDAAD//wMAfxRohPMDAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_5e3ab89dd1164922b68cd8a91afb4dd1.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5e3ab89dd1164922b68cd8a91afb4dd1.trn new file mode 100644 index 0000000..8742053 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5e3ab89dd1164922b68cd8a91afb4dd1.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTS0/jMBD+K5HPdXBsJ3FyA1q0FWKpoNpd7c0eT6hFcCrH4SHU/75yWsSyt73E0cgz8738Trx+QtKS8/1+9Yw+jmRBoptLnPGKsoYW9ZaVrVStbHKlmkpU8jdZEHeNb6QltQQooEEqsEIqLSupER1Qa7EpWGEZL2WaqR9G0r4T7XKLzw4wH8YfGEY3eNKSn87b4SXt1i6HfphsHoYe136M2kMCs1zdX29vN/Sqrr6vLi6ON0cc04DcWdKSqkOjrC5p3TRAJTSGqrqpqdaisx2W6Ty2OR8xeN3no338xGCH6DFCy3MuckZ5Qw4LYnXUCbbRI27f9gnJLNMy1Rdzef5t38kzBtLyxYegx3Fn0Luzp9FMrrdnx2/U42Niug/DHkN0OOsyU+17Hd3gs9Omy96hj2RBbu+zTa9jN4SnL2LdH/mv/4P+Nm1fvSJMEe3lMPlIWqLIgtxo2DmP2XqZhhXSyoZZKgujqay7hmoUmpqyaqQywlaYTL0cfHR+GqYxW/uID2GGT1pypfsRj8DPA+xcRIhTSJx+ValxEwY7Qcw+1S9YznLBRGqa4n6K2R1aFxAiJnbbMJ3m/dPCK85YgjKFgD5mGx132Tc97tIFW9sSOKIthKmZ6bBUVpUKaltVqupAlsBEUYKUIDpjG21MI4BL3hmJdUUWBJPZ2ZwvbQ2zrKip6rim0uqCKgBGrapBAGCBUHzRMbvtU5/pass447TRqqJSGEGV4IJKxlkttIKqSFH6kOTkvUyeXGPw2P9F+cZBGMahi9kpBNkXEe4mn95uNgfixXn6Oqu9HOARQ5bc0s6nmJ4MOhwOhz8AAAD//wMACwdnnQIEAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_7f218358f90d4dea89beb22e746aaa5e.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_7f218358f90d4dea89beb22e746aaa5e.trn new file mode 100644 index 0000000..54d09a2 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_7f218358f90d4dea89beb22e746aaa5e.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSTS2/cIBSF/4rF2jgYsA3e5alGUZooGbVVdzyuExQHRoDzUDT/vcIzVZvuusHoinM5fOf6A3n1DGhEx9vt+Qv4nFCNsltLlNAeE4nbYUO6kYuRy0aInhJJfqIauSt4RyMauDGtkYAZ9IC5JR3WbDLYWpAtaS2hHS891UNC4wdSrrHw4gw0IX2DmFzwaETfnbfhtdytXGPmsNgmhhkufcrKm2Lm7Pz+anNziy+G/uv5ycn+ZIJUGjTOohH1E2hhVYcHKQ3mRmosBjlgpdhkJ+jKdy9zPkP0am6SffrjwYbsIZuRNpQ1BFOJdjWyKqtiW6sEm/dtcbJiOiv1ei2v2/EDvUBEI61/A923OzKzO3pOenGzPdqvWaWntK6TMjnEd1SjbQxbiNnByug4JXjW8/tGpaeL/ZmyTedvYJYM9jQsPqMRCVSjFdE8q+yCrw4OT2cHPqMa3dxXt7PKU4jPnyDf77ld/ge2a2UenYfq8qxoWm65JBbzVivMh0liBUxh3fWSC81sDyXz0+Cz80tYUnXpMzzE1SUa0YWaE+z9HUfz6DKYvMRi/UdfhLcx2MXk6k84LWlIwwgroiVvl1zdgXURTIbyiE1cDv3+kdCeElKsLDGCz9Wtyo/VF5UeywE72M5QANsyPRA9QSes6IQZbN+LfjK8M4S1neHcsElbqbSWzFBOJ81h6FGNoMxCtY6fsUQTbQQeqLGYc9liwcSAmSJaU2HEpOUnjtXNXHR6GiyhhGKpRI850wwLRhnmhJKBKWH6tkzabySHiHnJ/gqih/mvJ187E0MKU64OWVefINwtvvza1Zr7q/P4baV9FswTxKqkpZwvU3wIaLfb7X4BAAD//wMA4dUdUiEEAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_a1db53cd4756496796a45e4d0e060b23.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_a1db53cd4756496796a45e4d0e060b23.trn new file mode 100644 index 0000000..f7486e8 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_a1db53cd4756496796a45e4d0e060b23.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSUTW/cNhCG/4rAsyhTJMUP3ZLYQV0j9SJeNEVvQ3JkC9FSC4raNDD2vxfUbuCmt5xIDPgOZx6+nFcS4YCkJ++Ox7sTxryQmuRxC3HGFWWWtnrPul6aXtpGWGN5K/8mNRkf8DvpiZbet94iFaiQysA66sTgaQhoW9YGxjtZcsLzQvpXAmMT8DR6bOblT0zLOEfSky9jDPO3cjeMjZ/mNTRpnvA+LhmiL8Xc3j097B939KNWf9y9f385ueBSEjRjID1RAzoToKPaWk+lt44abTUFEEMYsCvrRTbGjCnC1Czh61sNYc4Rs+95w0XDKLfkXJMAGUrZDhbcfz+WSjZMtyVeb+Ft27+SEybS8/oH0Eu6Gz+NN3k+TnjC6QhpwXTj58MBYiA1Oab5iCmPuKHZup0myOMcq+tlH6YRYyY1eXyqdhPkYU6Hn3g9XRDc/wKBEyZHetKZDkSrEWQwaMOgOuS2E6ZlKCUIzQODYZBK+KCYVQMCD156r1vOgxWK1OR5mh1Mvy8bP8uZM4FprjhKtFwqZT1DYXDoNLIASjllvA3CaC5NMAIsQGsdam+VLyb5BP5ljFjd35ZuWhmkZYHK1gGVerAUUAB1nbLSOBEUFs2HOeYxrvO6VPcx43Pa+JGefIRpwQu5d8m/jBl9XlOB+pcqwl2aw+pz9eaAljWsEUwU0ZqPa64+YxgT+owF7z6t13z/k3DFGSulrClhzNUO8kv1Gywv5UDQofMcMbTCaeYG7EwwnfE6KGXU4GXnmWg7L6UXgwsWnLPCc8kHJ1EXylgMV20ed8xLaNFT7V1HJVhDQYKhxjDDW9VxZouv3jhWj9OmG3RgnHFqwSgqhRPUCC6oZJxpAcarttj5B5Kr+aQhNXnAFHH6T8ufRp/mZR5ydXVh9ROEz2ss86PaHPltjPSfjfbt7L9iqsprwRjLV7k+0LkmB4RlTXjYxk//Snbln1T7bQpx1TBjTE2eMqS8Hq/hrmsMk+fz+fwvAAAA//8DALVuXjbCBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_ace67540371e4eae93f6d0895b617653.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_ace67540371e4eae93f6d0895b617653.trn new file mode 100644 index 0000000..e621363 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_ace67540371e4eae93f6d0895b617653.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRU207kOBD9lcivGwffEtt5A7rRIsRF063d1b75UgEvaaflODAI9b+vkoYBZrQP+xJHJVfVqXOO6xVFswPUotP9fv0EMY+oRDksIUZYg4nGVG5J3QrVCl0pzZlk9d+oROEKXlCLpHCOOg2YQwNYeFJjyzuHvQdNCfWE1WKuae5H1L4iEyoPT8FBNYx/QBrDEFGL/gzRD89zbxMq1w+Tr9LQw2Ucs4luBrNab662t3f4QjY367Oz480RxrlAFTxqUdOBVd7UWGrtsHDaYiW1xMbwzndQz+cxLcQMKZq+Gv3jBwY/5AjZtaxivCKYaXQokTfZzLCtGWH7sp+RLDSt5ni5hJff9hU9QUItK98JPZY7cX042Y12Cr0/Wb6oRPs07CHlAAsjy5B9b3IYYvHW47wPEDMq0dmcspmcg3FELdqmCd6j63gfIlwks4PnIT3eHNtWN+stKtFdGv4Bl+9MfkAt4p1TvrOOGqFtZ8HrhtQGtOmEFarznlPXOUY70khpmei48taappG1t5YxVKLbTXHXm9wNafdFr81Rgsv/ocDm9Hwdje1hzrkw/fhjpK1J95BRiyylnVNSa+FZrT0H4xQI2lhPjFIcBHgute6o4pxxRTtFrNKmVsTWIDxHJbocN9lEb/ohwvo7uGnm94PCa+MeQoTicjUDp8ILTTwW1BosZKexAW6wrRstlOW+gdnD50PMIU7DNBaXMcN9WjT7NMTtpjhN7iFkcHlKsxx/NXPiXRr85HLxYTZKKlJxMgO9nfJ+ysU38CGBywsrbyBvNz+nsIYRMkOZUoKYi1ng4nczzipTL33tGICn3EpiO6iVV7Vy0jeNajonakc4rZ0QjnfWa2Ot5o4J1lkBskElgtnbxfKcrGkceEewB6OwUKrBhmuPQVsKXBkpmPjCY3HbL3md9IQRhrVRDRbccqw441gQRiQ3yjXUfLXwpxFV1VRUVFyqhZp33t5ehVCoRFeQIvSfeLkOLg3j0OXizZXFF6Y+NVqFcd+bl1/6/QaSk456K9/vnz+Ae/zVpN+mOO/GYnH7c4j4+yLvanCPkIrZHibEeQ38yLie+hy2DwmMB389ePi56KFEOzDjlGC3bN9lIURIC4zVdLTYZbwOfR9GcEP0I2oFUxUlgr6h/c9rmlVSE3U4HA7/AgAA//8DADlZ+rXpBQAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_b532e6064ddb4074a63b8d295ce297d9.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_b532e6064ddb4074a63b8d295ce297d9.trn new file mode 100644 index 0000000..e9d61aa --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_b532e6064ddb4074a63b8d295ce297d9.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACoxTTW/bOBD9K8KcRYUSqQ/q1sQJNkhbB7V3u9gbP0YOEYU0KCptEPi/F5Sdtm572JOE0ejNm/fevIKTTwg9vNvvr5/RxQlyiHYpVbRqCBWkbLe07nnXc1Hwpu2qlv4HOdg7fIEeWq51qQUShg0SbmhNFBs0MQZFSUtDq5onTLmboH8FaQuDz1Zj4ad/MEzWO+jhs3XGf0mzpS306GdTBD/irZuidDqRWV1v7rbre3LTNh+vLy+PnRNOCaCwBnpoBlSdkTVphdCEa6FI14qWSMkGM2CdnsffrIsYnByLyTz+4GB8dBh1XxUVKyipBBxyMDLKRFvJCbcv+8RkkWmV6vlSXl77V3jGAH2Vvwl6hLvQo714mtRsR3Mx+t3Out2Vd4PdzUHGNDiHffB7DNHiItB6k/3gVNKCFlVTUQo5fJD6wTrMblfZekwbq6E1tKIVEbJrCGeKkY5VjHBa0ZbJTjdlInmHweH4E+oHq4Of/BCzk+7Z2Zwr76J1s5+n7NZF3J2I9nAjxwlTwxwCupjdy/iQ/SWnh8TUtKbWFaIpmWqpGrDuTFd3ujVN0zWD5rWmrKw155oNygiplGC64tWgOLYN5LDF8GSdHN/73S5p+X3e+YcVDnIe48bPYUnGZB4hh0vrZHg5dvw9oTl1fTya8Ya0BGocl4Wyk59Xo0UXz/RNaSq54YIawkslCW8HQSQySVTdCN4pZhpMsb4P3sw6/moZowxy+DS7dErZbTLri3Xka8N/ofoTN0y5ypYoCymVarQgjFEkvCkrIriQhCGTkg+a8UFADiuvHzFkyS9p3RnYepO9C/rBRtRxDmnNf5fZ6012P8o4+PB0dnbrOe7nmH1CYwPqiInFNswJ6saO+BvZt71PGvIOctgcr3HZ9n8e45V3k/8D/B8dhx7kHD0cDofDNwAAAP//AwDB5+uJuAQAAA== \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_f3a1d0f218a5492cacc3df523c5ff9b2.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_f3a1d0f218a5492cacc3df523c5ff9b2.trn new file mode 100644 index 0000000..073bb91 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_f3a1d0f218a5492cacc3df523c5ff9b2.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTy07cMBT9lcjrODi248TZwQyoCFEQjNqqOz9uGItgjxyHh9D8e+XMIEp3XcW68jk+j5t35NUToB6d7nbnz+DThEqU3DKihApMJK7bDWl63vVcVpIwSrr2NyqRu4I31KOWG1MbCZiBAMwtabBmg8HWgqxJbQlteOZUDxPq35FylYVnZ6AK0w+Ikwse9ein8za85LeVq8wYZlvFMMKln5LyJotZn99fbW5u8UUrvp+fnR1uTjBlgspZ1CMxgO6sanArpcHcSI27VrZYKTbYAZr8PcCcTxC9GqvJPn5qsCF5SKanFWUVwVSifYmsSirL1mqCzdsuK1liWud5uYyXY/+OniGinpYfgR7oTszoTkx4elLengzOu2mLSrSLYQcxOVgiWVyOo0ou+OL4yGp04BMq0c19cTuqNIT49CWn+4P1y/9wfq3M1nkoLtcZU3PLJbGY11ph3g4SK2AK60ZI3mlmBeTaVsEn5+cwT8WlT/AQF5WoRxdqnOCg7zSarUtg0hyz9F8iA+HVpVWweUBQiW5jsLNJxWfcNalIxQjLHHPazam4A+simATZ0ybOR/p/IFRQkhlXc4zgU3Gr0rb4pqZtvmBb2xgKYGumW6IHaDrbNZ1prRCdGAxvDGF1Yzg3bNBWKq0lM5TTQXNoRdad2y2WhSINlxKswMKQBnMuNdaSMtxo0tq2YVTorP4z1uJmzDg9tJZQQrFUncCcaYY7RhnmhJKWqc6IOu/ORyTHxnmHSnQF0cP4l+VrZ2KYwpCKY/XFlxDuZp9/1mJZgxfn8esS/jqYR4hFLk85n/fy2Nd+v9//AQAA//8DAB8jFwPzAwAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_55c23537298a4cdd905fff2a066c61c8.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_55c23537298a4cdd905fff2a066c61c8.trn new file mode 100644 index 0000000..7e7861e --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_55c23537298a4cdd905fff2a066c61c8.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSUS2/dNhCF/4rAtSjzJT60S2IHdY3URmw0RXdDcmQL0aUuKMppYNz/XlC+gZvusiMGPMPDj4fzQhIckAzk3fF49YyprKQlZdpLgglNmaPcPLB+UHboWccsF9rwv0lLphv8TgZiVAg8OKQSNVIVWU+9HAONER1nPDLRq9oTHlcyvBCYuojPU8BuWf/EvE5LIgP5MqW4fKtnw9SFedlil5cZr9NaIIVq5vLq/ubh9o5+NPqPq/fvX3euuNYG3RTJQKKzIVghqTGipwowUDcCUAAZIcKoneOvsikVzAnmbo1f3zzEpSQsYRCdkB2jwpFTSyIUqLY9rPjw/Vid7Jgua73dy/tyeCHPmMkg2h9AX9tdhHm6KMtxxmecj5BXzBdhORwgRdKSY16OmMuEO5r9tvMMZVpScz7swzxhKqQlt/fN3QxlXPLhJ173rwiuf4HAM2ZPBiJZL7UxqKSU4LQXDKPRQWvhAzAzeoE8IOudMo4bxqUTzMleG2siMBdISx7nxcP8+7rzc4J5G5kRWqBCJ5TWLjCUFsfeIIugtdc2uCitEcpGK8EBcOfRBKdDDcknCE9Twub6kgxEcxWVY5Eq7oEqMzoKKIH6XjtlvYwaq+bDksqUtmVbm+tU8DHv/MhAPsK84iu5dzk8TQVD2XKF+peuwru8xC2U5i0BnHWsk0xW0VaOW2k+Y5wyhoIV70Pezv3+JxFaMFatbDljKs0dlKfmN1if6oZoYh8EYuTSG+ZH7G20vQ0mam31GFQfmOR9UCrI0UcH3jsZhBKjV2g0aQnWwDV7xsMYjRo9Uo9CUqUsp1b3hkouNToEiLuRN47N7Vx1fjSRCSaoA6upkl5SK2sHJpiRYIPmNc4/kJzDpyxpyQ3mhPN/rvxpCnlZl7E05xQ2P0H4vKU6P5o9kd+mRP/ZaV8u4Svmpr4WTKl+lfMDnVpyQFi3jId9/Awv5K7+k+Zhn0JCdZpz05L7Arlsx3NZ6c4xrU6n0+lfAAAA//8DAMJGy6DDBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_6247cb09d42c4e96ace11389a1a91bf7.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_6247cb09d42c4e96ace11389a1a91bf7.trn new file mode 100644 index 0000000..18211b7 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_6247cb09d42c4e96ace11389a1a91bf7.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSUy27dNhCGX0XgWpR5v2iXxA5qGKmN+CAtuuNlFBPRoQ4oymlgnHcvKJ/ATXfdEQPO8J9vfs4Lyu4IaETvTqebZ8h1RT2qaQ8xwhQmFlN9IHIUZpRkoMRYQsVfqEfpDn6gEWkRAg0WMAcFWEQisedTwDGCpYRGwqRoNd3XFY0vyKUhwnMKMCzrFyhrWjIa0R8px+V7e9ulIczLFoeyzHCb1+pyaGKubx7vDvcP+KNWv9+8f/96c4W1FRhSRCOK1oRgGMdaM4mFg4Dt5Bx2jkcX3aSspa9pKVco2c3DGr+9aYhLzVDDyAbGB4KZReceRVddk+3dCocfp6Zkx3Td4v0e3o/jC3qGgkbW/wT6Wu4qzOlq3fwMzzCfXFmhXIXleHQ5oh6dynKCUhPsaJ6h+GVNtVENQTtjKI3GaSF1NFwyriMnEA3RMtponRJqYkHKKXpjtZhEZFREBUJ4jXq0w5tnV9OSu4v2D3OCXFGP7h+7h9nVaSnHX/A/vhK9/R9Am2w0Ik4kV1qD4Jw7qzwjELUKSjEfHNGTZ0ADEGmFtlQTyi0jlkuljY6O2IB69MmFp5Shu71GI1JURGFJxIJ6h4WeLHbAHfZSWWE8b42iHn1Yck15W7a1u80Vvpa9XzSij25e4bXTdyU8pQqhbqVB+FO1xIeyxC3U7s0AlAxk4IS3pK2ettp9hpgKhAoNx6Fsl3r/SWGKEdKkbKVArt2Dq0/db259aheijjIwgEi518RPIE000gQdlTJqCkIGwqkMQgQ++Wid95YHJtjkBWiFegTNb91u8TBJyi112BhtsIheYi8Nw0QqYo0xOoo2kTeO3f3c8vykI2GEYeuMwoJ7jg1nHAvCiObOBEWbm38iuZhFGNSjOygZ5n+1/CmFsqzLVLuLa7pfIHzeclsf3e6g7ynjv3fa10v4BqVr03Ipt59yGdC5R0dw61bguG+f8QU9tG/SHfYlxMSgKNU9eqyu1O10CQs1WKLE+Xw+/wMAAP//AwC8ws6OwgQAAA== \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn new file mode 100644 index 0000000..31ea21a --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACoyUTW/bOBCG/4owZ1GhSOrz1sQJNsi2Tmu3u9gbRY4cIgppkFS6QeD/vqDsbOp2D3sTRqN3nnlnRq9g5RNCDx/2++tntDFADtEsIUZZTWhHymZLq160fUWLsmmrqhJ/QQ7mDl+gh0YoVaoOCccaidC0IgMfFdEau5KWmrJKJE25C9C/gjSFxmejsHDhG/pgnIUe/jBWu++ptjSFmtysC+8mvLUhSqsSzOp6c7dd35Obpv50fXl5zAwYkkBhNPSgu1aplnHSNKwiQqIi3SglkZJrqeVYd115/MzYiN7KqQj68Z1Bu2gxqp4VjBeUsA4OOWgZZcIeZMDtyz6RLDatUjxfwstj/wrP6KFn+ZuhR7kLNZmLpzDMZtIXk9vtjN1dOTua3exlTIVz2Hu3Rx8NLgatN9k7U0kLWrCaUQo5fJTqwVjMblfZekodD2OjKaOMdLKtieADJy1nnAjKaMNlq+oyQd6htzj9oPrRKO+CG2N28j07q3PlbDR2dnPIbm3E3Qm0hxs5BUwJs/doY3Yv40P2mwwPiVQ3ulIMUZd8aOgwYtXqtmpVo+u6rUclKkV5WSkhFB8H3clh6Lhigo2DwKaGHLbon4yV0+9ut0te/lvv/MUKRzlPceNmv2xG0I+Qw6Wx0r8cM74G1KesT8dhvCktCzVNS0PZaZ5Xk0Ebz/yFHupSaNFRTUQ5SCKasSMSuSRDVXeiHbiuMa31vXd6VvHnkXHKIYcvs02nlN2mYX03lvxdi59Qf2DDtFfZssp1Q5EPoyZIO0GEGJFIHCnRVOMoq6qsaAc5rJx6RJ+leUljz8TWm+yDVw8mooqzT23+udReb7L7ScbR+aezs1vPcT/H7Atq41FFTBRbPyepGzPhL7BvfZ88FO1xb4J7y/2GfnDBxPSL+DwbTAZvjue62PE/r/VM853pPzcCepBzdHA4HA7/AAAA//8DAL7u70zYBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_dcc554cb89e74159855b8fda6d16c235.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_dcc554cb89e74159855b8fda6d16c235.trn new file mode 100644 index 0000000..03c8086 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_dcc554cb89e74159855b8fda6d16c235.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACoxUy27jOBD8FYFnUaFI6mVgDxknwQbZjI3Ys7vYGx/NmIhMGhSVTBDk3weU5YkzmMPeCLIfVdXVfENO7AEt0OXhcP0MLg4oR9FOV5TQGpMOl82WVAveLipS1C1rSMn/Qzmyd/CKFqjhSpWqA8ygBsw1qbBkRmGtoStJqQmteKopHge0eEPCFhqerYLCD39DGKx3aIH+sU77l9Rb2EL1ftRF8D3cuiEKpxKYq+vN3Xa1xjdN/fX6y5dj5ABDKlBYjRZId61SLWW4aWiFuQCFOyMEFoJpoYWpu648plkXITjRF4N++sCgfXQQ1YIWlBUE0w6950iLKBJsKQbYvh4Skkmmq3SfT9fTcfGGniGgBc1Pgh7LXajeXuwHOdpeX0QRHiGaIPbw4sMTPIse5egQ/AFCtDDps9pkH5BKUpCC1pQQlKN7oXbWQXZ7la36RFiaRhNKKO5EW2POJMMtowxzQknDRKvqMmG8g+CgP6t6b1Xwgzcxm2XPPvVZehetG/04ZLcuwmMQ8Zh3I/oBUI7Wo+ztsHsAoV+3/mFMb27sE5flGAK4mK1F3GV/imGXSOhGV4oC6JLJhkgDVavbqlWNruu2NopXirCyUpwrZqTuhJQdU5RTIzk0NcrRaoyHMZ70/34GYhvsfg/6A8F20njdi2h82N9qcNEam0ZziphM1fcTq2yuuewtuPhJZLRAdck174jGvJQC88Z0WAATWFZ1x1vJdA3J2kvvjH0cf+pEjNGcmapta9nJkgA1TctJYyTRyjDV6UpCQxvStNB2ihBZ8bKVnSIayorrxC54Par4qxUYYShHD6NLG5rdJtov1uHvNf9QZB189Mr3aWC2h83rEGH/u6kt/f7gBxsTfzOP9tsA996l1/kPmDWbky99PAuGtAjZtHtJFg2c4k7VDHNtGiwp0biuW97UXDDQHcrRlVdPELLkMGHdNJSTqVab7DKonY2g4hhS638nVsd53px25kOQ4uv1dukDXB4O+Xz7x3NXJAevNtnJAJ/+lm9Dit75IbGIYTzz0QZ6c4J15qaj8bIH0DaAitPT9pg4a/Q7h12GaI1QcUhr8JdXkzFmp80hv/Y7G8DP7GPzsyHMppgr8XaqM/2AkxX+1wf4/v7+/gMAAP//AwCxdSWE9QUAAA== \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054856_09e56a2b38574bdb8e196ea189c58142.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054856_09e56a2b38574bdb8e196ea189c58142.trn new file mode 100644 index 0000000..ac3ed9b --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054856_09e56a2b38574bdb8e196ea189c58142.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTTU/cMBD9K9Gc4+DYjvNxoyxVEWpBsGqr3ib2pFgEZ+U4fAjtf6+cXUTprRfLGvnNvPfm+RU8PhB0cLrbnT+SjzPkEN1aElxoxltW1ltedarpKl00Uopa6l+Qg7ukF+igVsaUpiUmSRNTllesl4Nh1lJb8tJyUanUE3/P0L0CusLSozNUTPN3CrObPHTww3k7PaXZ6AozTostwjTShZ8jepPIbM5vL7dX1+xzrb+df/p0eDnTnBoUzkIHtm2MaYRkdS0qppAMawdEhigtWhx025YHmPORgsexmO39Owc7RU/RdKIQsuBMtLDPwWLERLvHmbYvu8RktWmT6vlaXq/dKzxSgE7kb4Ye2p2Y0Z08zP3iRntyOCPO90npLkw7CtHR6ssqdRwxuslnx0lnoyMfIYer2+x6xDhM4eGDWbcH/Rf/IX+bpp8/k1ki2bNp8RE6UAJy+IrmznnKLjbQgS6VVS23TJU9MlUPLUOSyPpKt6rppdWUtno2+ej8Mi1zduEj/Q4rf+jgM44zHZifBnPnIpm4hCTqp07A6zDZxcTs3f6SF7yQXCbQEndLzG7IukAmUpK3Dcux3z8QoQXnicoSAvmYXWO8y77gfJce2NpWRhDZUvY17weqGttUjamt1o0ejKoMl2VllDJy6G2Lfd9KI5QYekW1hhwobTtbA9YS15wImUbNmdKVYNhzYkZz5FXbN7ZMmXj3MbsaE64fassFF6zFRjMle8kaKSRTXPBaYmP0inuz5Lh81UAOlxQ8jX9J/upMmOZpiNkxBdkHE24Wnz5vtibiyXn2vLq9mcw9hSxtC51POT0uaL/f7/8AAAD//wMAd4cViwMEAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054856_3e9580a6a36741b390d50bd290250e42.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054856_3e9580a6a36741b390d50bd290250e42.trn new file mode 100644 index 0000000..54605b1 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054856_3e9580a6a36741b390d50bd290250e42.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTXW/bIBT9KxbPwcWAMfitbVotqrpGbbRNe8Nw3aA6EGHcD1X57xNOqq5725t1xTn3fFy/I693gFp0vt9fPYNPI1qg5OYRJVRgonDVbEjdctnWopSMM0bVb7RA7gbeUIsabkxlFGAGAjC3pMYd6w22FlRFKktozTOnfhxR+460Ky08OwNlGH9AHF3wqEU/nbfhJe/WrjRDmGwZwwArPybtTRazvHq42dyt8XUjvl9dXBxfjjBmgtJZ1CKrpDGSMtw0tMZcg8Gq1xprzay2uhdKVUeY8wmi10M52qdPDTYkD8m0tKSsJJgqdFggq5POsjs9wuZtn5XMMS3zfDGP58/2HT1DRC1dfAR6pDszgzszYbfT3p71zrtxixZoH8MeYnIwRzK7HAadXPDFacnl4MAntEB3D8V60KkPcfclp4ej9dV/OL/VZus8FKslapGouOWKWMyrTmPe9AprYBp3tVBcdswKyLVdBp+cn8I0Fiuf4DHOKlGLrvUwwlHfeTRbl8CkKWbpv0QGwqtLl8HmQd69jsFOJhWfcVekJCUjLHNMaT+l4h6si2ASZE+bOJ3o/4FQQQnJyqYYwadirdO2+KbHbX5gG1sbCmAr1jWk66GWVtbSNFYIKXrDa0NYVRvODes7q3TXKWYop33HoRFZd263mA+qMY1QnQbMOasxZ12HOwUWV5KQCqSESvdfYi3uhozr+sYSSihWWoqMY1gyyjAnlDRMSyOqfDsfkZwa5xIt0A1ED8Nflm+diWEMfSpO1RdfQriffP5Zi/kMXpzHr3P4y2CeIBa5PO18vstTX4fD4fAHAAD//wMA/WXCnPMDAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn new file mode 100644 index 0000000..17e624d --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRUy27kIBD8FYvz4GDA2PiWpzaKsok2o+xqbzzaCYoDI8B5KJp/X+GZKDun1V4QancX1VUlfyCvngEN6HizOX8BnxNaoeyWEiVUYCJx061JO/B+aEXdU0lb2v1GK+Su4B0NqOPGNEYCZiAAc0tarNlosLUgG9JYQlteMNVDQsMHUq628OIM1CHdQ0wueDSgn87b8FreVq42U5htHcMElz5l5U0hc3Z+d7W+ucUXnfh+fnKy60yQCkDtLBqQlb0xPWW462iLuQKD5agUVopZZdUopGx2Y85niF5NdbJPXxxsyB6yGWhNWU0wlWi7QlZlVWhrlWD9vilMFpnOSn21lJfr8IFeIKKBrj4F3cEdmckdPSc9u8ke7c6s0lNazlGZHOI7WqFNDBuI2cGi0XFK8Kyn97VKTxe7nnJN529g5gz2NMw+owExgVZo0WiaVHbBV3uKp5MDn5ePOTqfnPkXVEG6uatuJ5XHEJ8PLLnbqXz5HyJfK/PoPFSXZwW74ZZLYjFvtMK8GyVWwBTWrZC818wKKAk5DT47P4c5VZc+w0NcVkIDulBTgh2/42geXQaT51j2/CXK4G0Mdja5+rKyITWpGWFlaM6bOVc/wLoIJkNZYh3nPd794QgVlJBCZY4RfK5uVX6svqn0WBpsZ1tDAWzDdEf0CG1v+7Y3nRWiF6PhrSGsaQ3nho3aSqW1ZIZyOmoOXREYSnKqJaySso522mA7tgJzYhusjBW4oVJT23R2pPRAx+pmKnN67CyhhGKpeoE50wz3jDLMCSUdU70RTcnlpyT7PPAerdAVRA/TXytfOxNDCmOu9l5XByL8mH35EVSL76/O47dF7bNgniBWxS3lfMn83qDtdrv9AwAA//8DAJ9uh65PBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/7b4fdabac24445e18bb7e730fceaf989 b/Distribution/.dotnet/TelemetryStorageService/7b4fdabac24445e18bb7e730fceaf989 new file mode 100644 index 0000000..5dbb49f --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/7b4fdabac24445e18bb7e730fceaf989 @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRVTW/jNhD9KwKvlbQSKZGSgD1kHWcbLPKB2OgWvQ3JYcxGIQ2KyjYN/N8LyknX2UUPvdjSSDPz5r031Atx8IhkIGf7/foJXZxITqJdQrSivKj6ohbbqh2abmh52bGu5XX/B8mJ/YLPZCCiUapWPRYMORaNrtpCMqMKrbGvq1pXtG1STbifyPBCwJYan6zC0k+/YZisd2QgX63T/lvqDbZUo591GfyIl26K4FQCc77efNne3BYXgl+vP306vjnhlAqUVpOB6L5TqqOsEIK2RQOoit4AFABMgwbD+74+plkXMTgYy0k/fMegfXQY1UBLysqqoD055ERDhARbwoTb531CstB0nuL5El4uhxfyhIEMNH8j9Fjugxrth8dJznbUH5ZfkpN98HsM0eLCyDLkOEK03mWvPVajRRdJTj6llM2sFE4TGcgFjBO+hdfu3jq8CPCI33x4uD72La/XW5KT2+D/RBVvIe7IQJhRnTZS1dD00kjUPa9awB5MI5vOaM1qZRStTcWFkLQxrNNSAuei1VJSSnJys8luR4jGh8d3gm2OGlz+Dwk2Z6u1Azmi/nGkLYR7jGQgLW8lMtNRLjlo6FlnakDWayUZb7GTQncoBKMMVKuqrla1qFvoRdsKzmjqcjltIjgNo3e4/gvVnAgmA9mGOfW7ArWzDrPLczIQXje66StdNLWEohGmLwAZFLLlfdNJpjkmE1+AHeeAK4h470Ny//X8GZNOK++idbOfp+zSRbwPi5wn491ssrOgdjaiinNIQv3OU8nb4PWsYvbdh3VVViWrWEqa436O2R1qG1DFha9X+DebH1Mop1WVoMwhoItZkj77Faakf62FbhVF1DWTopIG2053baeE5rzjRjWtqljdqqZRzEjdg5Q9U7ShRjYoOMkJJttny6Y1XS8qo6DoIFHGelOAkrLg0vTQiKpjlXjHcHYzpjxphK5oRYseOl40TLKiY5QVTUUrwaBTvIb35j4ZsSt5WTclE91CzRtvrwvTdCQn6xB8WPk5nWLD6d2lMz57yVb+cW9HDNnHLM+upqXPZ3QYYDwNrZ9gnI/reBp9s9C77AD73RLYwvSwXGz0wx1OfnzCMC2Ba4wbfXy2uCX7mNV5tqSvdqhen0C0T7j1flQ7sMceK6/xzMH4PNljpTv42x/Bf92b5f9s2l8vFfPsJu6WybIDyckXDA7HE4dcWRX85E3MXjc3e+eZE8rP7bQf4fkn5n9BwSpTa5mk/Y7+50W+m136gGTLifDNuuKvxejnXj1gyNKigHXprPw342oeo93uAoJGfeU1/lj0kJNHhGkO+Lh8opZT02FYYJzPx2W7dFd2HO2Eyjs9kYFz3pSM0/YV7n++JxpaVqzmh8Ph8A8AAAD//wMADw4oQRAHAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/10.0.303.1/microsoft.net.workloads.workloadset.json b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/10.0.303.1/microsoft.net.workloads.workloadset.json new file mode 100644 index 0000000..8e0f001 --- /dev/null +++ b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/10.0.303.1/microsoft.net.workloads.workloadset.json @@ -0,0 +1,18 @@ +{ + "Microsoft.NET.Workload.Emscripten.Current": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net6": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net7": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net8": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net9": "10.0.111/10.0.100", + "Microsoft.NET.Sdk.Android": "36.1.69/10.0.100", + "Microsoft.NET.Sdk.iOS": "26.5.10315/10.0.100", + "Microsoft.NET.Sdk.MacCatalyst": "26.5.10315/10.0.100", + "Microsoft.NET.Sdk.macOS": "26.5.10315/10.0.100", + "Microsoft.NET.Sdk.Maui": "10.0.20/10.0.100", + "Microsoft.NET.Sdk.tvOS": "26.5.10315/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.Current": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net6": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net7": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net8": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net9": "10.0.111/10.0.100" +} diff --git a/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/AdvertisedManifestFeatureBand.txt b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/AdvertisedManifestFeatureBand.txt new file mode 100644 index 0000000..d43750c --- /dev/null +++ b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/AdvertisedManifestFeatureBand.txt @@ -0,0 +1 @@ +10.0.300 \ No newline at end of file diff --git a/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/workloadVersion.txt b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/workloadVersion.txt new file mode 100644 index 0000000..bc93d3c --- /dev/null +++ b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/workloadVersion.txt @@ -0,0 +1 @@ +10.0.303.1 \ No newline at end of file diff --git a/Distribution/Data/AppDBContext.cs b/Distribution/Data/AppDBContext.cs index 16cd3f6..0393a15 100644 --- a/Distribution/Data/AppDBContext.cs +++ b/Distribution/Data/AppDBContext.cs @@ -17,9 +17,10 @@ public class AppDBContext(DbContextOptions options) : DbContext(op public DbSet UomConversions { get; set; } public DbSet Items { get; set; } public DbSet SaleRoutes { get; set; } - public DbSet Sales { get; set; } - public DbSet Orders { get; set; } - public DbSet OrderItems { get; set; } + public DbSet ShopPOs { get; set; } + public DbSet ShopPOItems { get; set; } + public DbSet Invoices { get; set; } + public DbSet LoadingSheetOrders { get; set; } public DbSet DeliveryRuns { get; set; } public DbSet Users { get; set; } public DbSet Roles { get; set; } @@ -36,7 +37,6 @@ public class AppDBContext(DbContextOptions options) : DbContext(op public DbSet Suppliers { get; set; } public DbSet DriverProfiles { get; set; } public DbSet DriverComplianceConfigs { get; set; } - public DbSet RideCancelRequests { get; set; } public DbSet Schemes { get; set; } public DbSet SchemeRedemptions { get; set; } public DbSet SchemeBundleComponents { get; set; } @@ -61,11 +61,11 @@ public class AppDBContext(DbContextOptions options) : DbContext(op public DbSet RegionAgencyMaps { get; set; } public DbSet RegionalTaxRules { get; set; } public DbSet RouteVisitLogs { get; set; } + public DbSet SysConfigs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity() - .HasKey(oi => new { oi.FK_OrderId, oi.FK_ItemId }); + // --- Composite PKs --- modelBuilder.Entity() .HasKey(rp => new { rp.FK_RoleId, rp.FK_PermissionId }); @@ -79,11 +79,10 @@ public class AppDBContext(DbContextOptions options) : DbContext(op modelBuilder.Entity() .HasKey(s => new { s.FK_UserId, s.FK_StoreId }); - modelBuilder.Entity() - .HasOne(u => u.ReportsTo) - .WithMany() - .HasForeignKey(u => u.FK_ReportsToUserId) - .OnDelete(DeleteBehavior.Restrict); + modelBuilder.Entity() + .HasKey(lo => new { lo.FK_LoadingSheetId, lo.FK_ShopPOId }); + + // --- Unique indexes --- modelBuilder.Entity() .HasIndex(sb => new { sb.FK_ItemId, sb.LocationId }) @@ -93,14 +92,20 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasIndex(pli => new { pli.FK_PriceListId, pli.FK_ItemId }) .IsUnique(); - modelBuilder.Entity() - .HasIndex(o => o.FK_SaleId) - .IsUnique(); - modelBuilder.Entity() .HasIndex(dp => dp.FK_UserId) .IsUnique(); + // --- User --- + + modelBuilder.Entity() + .HasOne(u => u.ReportsTo) + .WithMany() + .HasForeignKey(u => u.FK_ReportsToUserId) + .OnDelete(DeleteBehavior.Restrict); + + // --- Vehicle --- + modelBuilder.Entity() .HasOne() .WithMany() @@ -108,11 +113,7 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .OnDelete(DeleteBehavior.Restrict) .IsRequired(false); - modelBuilder.Entity() - .HasOne(r => r.SourceWarehouse) - .WithMany() - .HasForeignKey(r => r.FK_SourceWarehouseId) - .OnDelete(DeleteBehavior.Restrict); + // --- DeliveryRun --- modelBuilder.Entity() .HasOne(r => r.DriverProfile) @@ -120,30 +121,97 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(r => r.FK_DriverProfileId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() - .HasOne(s => s.Store) + // --- ShopPO --- + + modelBuilder.Entity() + .HasOne(p => p.Store) .WithMany() - .HasForeignKey(s => s.FK_StoreId) + .HasForeignKey(p => p.FK_StoreId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() - .HasOne(s => s.CreatedByUser) - .WithMany() - .HasForeignKey(s => s.CreatedByUserId) + // InvoiceId is a plain column — no FK constraint + modelBuilder.Entity() + .Property(p => p.InvoiceId) + .HasColumnName("InvoiceId"); + + // --- ShopPOItem --- + + modelBuilder.Entity() + .HasOne(i => i.ShopPO) + .WithMany(p => p.Items) + .HasForeignKey(i => i.FK_ShopPOId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() + modelBuilder.Entity() + .HasOne(i => i.Item) + .WithMany() + .HasForeignKey(i => i.FK_ItemId) + .OnDelete(DeleteBehavior.Restrict); + + // --- Invoice --- + + modelBuilder.Entity() + .HasOne(i => i.ShopPO) + .WithMany() + .HasForeignKey(i => i.FK_ShopPOId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasMany(i => i.Payments) + .WithOne(p => p.Invoice) + .HasForeignKey(p => p.FK_InvoiceId) + .OnDelete(DeleteBehavior.Restrict); + + // --- LoadingSheet --- + + modelBuilder.Entity() .HasOne(s => s.Ride) .WithMany() .HasForeignKey(s => s.FK_RideId) - .OnDelete(DeleteBehavior.Restrict) + .OnDelete(DeleteBehavior.Restrict); + + // --- LoadingSheetOrder --- + + modelBuilder.Entity() + .HasOne(lo => lo.LoadingSheet) + .WithMany(s => s.Orders) + .HasForeignKey(lo => lo.FK_LoadingSheetId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(lo => lo.ShopPO) + .WithMany() + .HasForeignKey(lo => lo.FK_ShopPOId) + .OnDelete(DeleteBehavior.Restrict); + + // --- LoadingSheetItem --- + + modelBuilder.Entity() + .HasOne(i => i.LoadingSheet) + .WithMany(s => s.Items) + .HasForeignKey(i => i.FK_LoadingSheetId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(i => i.Item) + .WithMany() + .HasForeignKey(i => i.FK_ItemId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(i => i.Warehouse) + .WithMany() + .HasForeignKey(i => i.FK_WarehouseId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(i => i.ShopPOItem) + .WithMany() + .HasForeignKey(i => i.FK_ShopPOItemId) + .OnDelete(DeleteBehavior.SetNull) .IsRequired(false); - modelBuilder.Entity() - .HasOne(o => o.Sale) - .WithMany() - .HasForeignKey(o => o.FK_SaleId) - .OnDelete(DeleteBehavior.Restrict); + // --- SchemeRedemption --- modelBuilder.Entity() .HasOne(r => r.Scheme) @@ -152,10 +220,11 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() - .HasOne(r => r.Order) + .HasOne(r => r.ShopPO) .WithMany() - .HasForeignKey(r => r.FK_OrderId) - .OnDelete(DeleteBehavior.Restrict); + .HasForeignKey(r => r.FK_ShopPOId) + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(false); modelBuilder.Entity() .HasOne(r => r.FreeItem) @@ -163,6 +232,8 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(r => r.FK_FreeItemId) .OnDelete(DeleteBehavior.Restrict); + // --- Scheme --- + modelBuilder.Entity() .HasOne(s => s.TriggerItem) .WithMany() @@ -191,23 +262,7 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasIndex(c => new { c.FK_SchemeId, c.FK_ItemId }) .IsUnique(); - modelBuilder.Entity() - .HasOne(s => s.SourceWarehouse) - .WithMany() - .HasForeignKey(s => s.FK_SourceWarehouseId) - .OnDelete(DeleteBehavior.Restrict); - - modelBuilder.Entity() - .HasOne(s => s.Ride) - .WithMany() - .HasForeignKey(s => s.FK_RideId) - .OnDelete(DeleteBehavior.Restrict); - - modelBuilder.Entity() - .HasOne(i => i.Item) - .WithMany() - .HasForeignKey(i => i.FK_ItemId) - .OnDelete(DeleteBehavior.Restrict); + // --- PurchaseOrder --- modelBuilder.Entity() .HasOne(po => po.Supplier) @@ -227,6 +282,11 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(i => i.FK_ItemId) .OnDelete(DeleteBehavior.Restrict); + modelBuilder.Entity() + .HasIndex(i => i.FK_PurchaseOrderId); + + // --- GoodsReceipt --- + modelBuilder.Entity() .HasOne(gr => gr.PurchaseOrder) .WithMany() @@ -251,6 +311,14 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(i => i.FK_PurchaseOrderItemId) .OnDelete(DeleteBehavior.Restrict); + modelBuilder.Entity() + .HasIndex(i => i.FK_GoodsReceiptId); + + modelBuilder.Entity() + .HasIndex(i => i.FK_PurchaseOrderItemId); + + // --- PurchaseReturn --- + modelBuilder.Entity() .HasOne(pr => pr.PurchaseOrder) .WithMany() @@ -269,22 +337,15 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(i => i.FK_ItemId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() - .HasIndex(i => i.FK_PurchaseOrderId); - - modelBuilder.Entity() - .HasIndex(i => i.FK_GoodsReceiptId); - - modelBuilder.Entity() - .HasIndex(i => i.FK_PurchaseOrderItemId); - modelBuilder.Entity() .HasIndex(i => i.FK_PurchaseReturnId); + // --- SaleReturn --- + modelBuilder.Entity() - .HasOne(r => r.Order) + .HasOne(r => r.ShopPO) .WithMany() - .HasForeignKey(r => r.FK_OrderId) + .HasForeignKey(r => r.FK_ShopPOId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() @@ -308,12 +369,16 @@ public class AppDBContext(DbContextOptions options) : DbContext(op modelBuilder.Entity() .HasIndex(i => i.FK_SaleReturnId); + // --- CreditNote --- + modelBuilder.Entity() .HasOne(n => n.SaleReturn) .WithMany() .HasForeignKey(n => n.FK_SaleReturnId) .OnDelete(DeleteBehavior.Restrict); + // --- Claims --- + modelBuilder.Entity() .HasOne(c => c.AgencyUser) .WithMany() @@ -366,6 +431,8 @@ public class AppDBContext(DbContextOptions options) : DbContext(op modelBuilder.Entity() .HasIndex(i => i.FK_SupplierClaimId); + // --- DeliveryTask --- + modelBuilder.Entity() .HasOne(t => t.Ride) .WithMany() @@ -373,11 +440,13 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() - .HasOne(t => t.Order) + .HasOne(t => t.ShopPO) .WithMany() - .HasForeignKey(t => t.FK_OrderId) + .HasForeignKey(t => t.FK_ShopPOId) .OnDelete(DeleteBehavior.Restrict); + // --- Regional --- + modelBuilder.Entity() .HasIndex(t => new { t.FK_RegionId, t.Period }) .IsUnique(); @@ -400,6 +469,19 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasIndex(r => r.FK_RegionId) .IsUnique(); + // --- SysConfig --- + + modelBuilder.Entity() + .HasKey(c => c.Key); + + modelBuilder.Entity() + .Property(c => c.Key) + .HasMaxLength(100); + + modelBuilder.Entity().HasData( + new SysConfig { Key = "InvoiceCreationMode", Value = "ModeB", UpdatedAt = new DateTime(2026, 9, 17), UpdatedBy = null } + ); + Seed.RoleAndPermissionSeed.Apply(modelBuilder); Seed.MasterDataSeed.Apply(modelBuilder); Seed.OperationsDataSeed.Apply(modelBuilder); diff --git a/Distribution/Data/Seed/CommerceSeed.cs b/Distribution/Data/Seed/CommerceSeed.cs index a200354..9b2d64c 100644 --- a/Distribution/Data/Seed/CommerceSeed.cs +++ b/Distribution/Data/Seed/CommerceSeed.cs @@ -16,6 +16,9 @@ public static class CommerceSeed private static readonly Guid SchemeRedemption1Id = new("50000000-0000-0000-0000-000000000001"); private static readonly Guid Payment1Id = new("47000000-0000-0000-0000-000000000001"); + private static readonly Guid Payment2Id = new("47000000-0000-0000-0000-000000000002"); + private static readonly Guid Payment3Id = new("47000000-0000-0000-0000-000000000003"); + private static readonly Guid Payment4Id = new("47000000-0000-0000-0000-000000000004"); private static readonly Guid SaleReturn1Id = new("51000000-0000-0000-0000-000000000001"); private static readonly Guid SaleReturnItem1Id = new("52000000-0000-0000-0000-000000000001"); @@ -80,15 +83,18 @@ public static class CommerceSeed ); modelBuilder.Entity().HasData( - new SchemeRedemption { Id = SchemeRedemption1Id, FK_SchemeId = Scheme1Id, FK_OrderId = OperationsDataSeed.Order1Id, FieldInvoiceId = null, DiscountAmount = 0m, FK_FreeItemId = MasterDataSeed.Coke500ItemId, FreeQty = 1m, FreeItemCostValue = 40m, RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0) } + new SchemeRedemption { Id = SchemeRedemption1Id, FK_SchemeId = Scheme1Id, FK_ShopPOId = OperationsDataSeed.ShopPO1Id, FieldInvoiceId = null, DiscountAmount = 0m, FK_FreeItemId = MasterDataSeed.Coke500ItemId, FreeQty = 1m, FreeItemCostValue = 40m, RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0) } ); modelBuilder.Entity().HasData( - new Payment { Id = Payment1Id, FK_SaleId = OperationsDataSeed.Sale1Id, FK_StoreId = MasterDataSeed.FortStoreId, Amount = 3000m, Method = PaymentMethod.Cash, CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0), CollectedBy = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0), IsActive = true } + new Payment { Id = Payment1Id, FK_InvoiceId = OperationsDataSeed.Invoice1Id, Amount = 3000m, Method = PaymentMethod.Cash, EntryMode = EntryMode.RealTime, CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0), CollectedBy = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0), IsActive = true }, + new Payment { Id = Payment2Id, FK_InvoiceId = OperationsDataSeed.Invoice2Id, Amount = 1000m, Method = PaymentMethod.Cash, EntryMode = EntryMode.RealTime, CollectedAt = new DateTime(2026, 8, 31, 9, 20, 0), CollectedBy = MasterDataSeed.SalesRep2UserId, CreatedAt = new DateTime(2026, 8, 31, 9, 20, 0), IsActive = true }, + new Payment { Id = Payment3Id, FK_InvoiceId = OperationsDataSeed.Invoice2Id, Amount = 800m, Method = PaymentMethod.Cheque, EntryMode = EntryMode.DayEndManual, ChequeNumber = "000456", ChequeDate = new DateTime(2026, 8, 31), CollectedAt = new DateTime(2026, 8, 31, 11, 0, 0), CollectedBy = MasterDataSeed.SalesRep2UserId, RecordedBy = MasterDataSeed.Supervisor1UserId, CreatedAt = new DateTime(2026, 8, 31, 18, 0, 0), IsActive = true }, + new Payment { Id = Payment4Id, FK_InvoiceId = OperationsDataSeed.Invoice2Id, Amount = 300m, Method = PaymentMethod.Credit, EntryMode = EntryMode.RealTime, CollectedAt = new DateTime(2026, 8, 31, 11, 5, 0), CollectedBy = MasterDataSeed.SalesRep2UserId, CreatedAt = new DateTime(2026, 8, 31, 11, 5, 0), IsActive = true } ); modelBuilder.Entity().HasData( - new SaleReturn { Id = SaleReturn1Id, FK_OrderId = OperationsDataSeed.Order1Id, Mode = ReturnMode.CreditDeduction, TotalCreditAmount = 300m, CreatedByUserId = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 26), IsActive = true } + new SaleReturn { Id = SaleReturn1Id, FK_ShopPOId = OperationsDataSeed.ShopPO1Id, Mode = ReturnMode.CreditDeduction, TotalCreditAmount = 300m, CreatedByUserId = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 26), IsActive = true } ); modelBuilder.Entity().HasData( diff --git a/Distribution/Data/Seed/OperationsDataSeed.cs b/Distribution/Data/Seed/OperationsDataSeed.cs index bb502ef..f063b2f 100644 --- a/Distribution/Data/Seed/OperationsDataSeed.cs +++ b/Distribution/Data/Seed/OperationsDataSeed.cs @@ -8,15 +8,20 @@ public static class OperationsDataSeed internal static readonly Guid ClosedSaleRunId = new("31000000-0000-0000-0000-000000000001"); internal static readonly Guid ActiveDeliveryRunId = new("31000000-0000-0000-0000-000000000002"); + // Kept for OperationsExtrasSeed stock movement reference (ReferenceId on MovementType.Sale) internal static readonly Guid Sale1Id = new("32000000-0000-0000-0000-000000000001"); - internal static readonly Guid Sale2Id = new("32000000-0000-0000-0000-000000000002"); - internal static readonly Guid Order1Id = new("33000000-0000-0000-0000-000000000001"); - internal static readonly Guid Order2Id = new("33000000-0000-0000-0000-000000000002"); + internal static readonly Guid ShopPO1Id = new("33000000-0000-0000-0000-000000000001"); + internal static readonly Guid ShopPO2Id = new("33000000-0000-0000-0000-000000000002"); + internal static readonly Guid ShopPO3Id = new("33000000-0000-0000-0000-000000000003"); - internal static readonly Guid OrderItem1Id = new("34000000-0000-0000-0000-000000000001"); - internal static readonly Guid OrderItem2Id = new("34000000-0000-0000-0000-000000000002"); - internal static readonly Guid OrderItem3Id = new("34000000-0000-0000-0000-000000000003"); + internal static readonly Guid ShopPOItem1Id = new("34000000-0000-0000-0000-000000000001"); + internal static readonly Guid ShopPOItem2Id = new("34000000-0000-0000-0000-000000000002"); + internal static readonly Guid ShopPOItem3Id = new("34000000-0000-0000-0000-000000000003"); + internal static readonly Guid ShopPOItem4Id = new("34000000-0000-0000-0000-000000000004"); + + internal static readonly Guid Invoice1Id = new("34500000-0000-0000-0000-000000000001"); + internal static readonly Guid Invoice2Id = new("34500000-0000-0000-0000-000000000002"); internal static readonly Guid LoadingSheet1Id = new("35000000-0000-0000-0000-000000000001"); @@ -31,16 +36,12 @@ public static class OperationsDataSeed new DeliveryRun { Id = ClosedSaleRunId, - RideType = RideType.Sale, Status = RideStatus.Closed, FK_VehicleId = MasterDataSeed.VanVehicleId, FK_DriverProfileId = MasterDataSeed.Driver1ProfileId, - FK_RouteId = MasterDataSeed.ColomboRouteId, - FK_SourceWarehouseId = MasterDataSeed.ColomboWarehouseId, Meterstart = 10500, Meterend = 10550, StartedAt = new DateTime(2026, 8, 25, 8, 0, 0), - ActivatedAt = new DateTime(2026, 8, 25, 8, 15, 0), ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0), CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true @@ -48,86 +49,101 @@ public static class OperationsDataSeed new DeliveryRun { Id = ActiveDeliveryRunId, - RideType = RideType.Delivery, - Status = RideStatus.Active, + Status = RideStatus.Open, FK_VehicleId = MasterDataSeed.TruckVehicleId, FK_DriverProfileId = MasterDataSeed.Driver2ProfileId, - FK_RouteId = MasterDataSeed.KandyRouteId, - FK_SourceWarehouseId = MasterDataSeed.KandyWarehouseId, Meterstart = 20300, Meterend = 0, StartedAt = new DateTime(2026, 8, 30, 9, 0, 0), - ActivatedAt = new DateTime(2026, 8, 30, 9, 20, 0), ClosedAt = null, CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0), IsActive = true } ); - modelBuilder.Entity().HasData( - new Sale + modelBuilder.Entity().HasData( + new ShopPO { - Id = Sale1Id, - SaleDate = new DateTime(2026, 8, 25, 9, 0, 0), + Id = ShopPO1Id, FK_StoreId = MasterDataSeed.FortStoreId, - CreatedByUserId = MasterDataSeed.SalesRep1UserId, - FK_RideId = ClosedSaleRunId, + RaisedById = MasterDataSeed.SalesRep1UserId, + InvoiceId = Invoice1Id, TotalAmount = 3000m, - Status = SaleStatus.Completed, - PaymentStatus = PaymentStatus.Paid, - FulfillImmediately = false, - CompletedAt = new DateTime(2026, 8, 25, 9, 30, 0), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), - IsActive = true - }, - new Sale - { - Id = Sale2Id, - SaleDate = new DateTime(2026, 8, 30, 10, 0, 0), - FK_StoreId = MasterDataSeed.KandyStoreId, - CreatedByUserId = MasterDataSeed.SalesRep2UserId, - FK_RideId = ActiveDeliveryRunId, - TotalAmount = 1200m, - Status = SaleStatus.Pending, - PaymentStatus = PaymentStatus.Pending, - FulfillImmediately = false, - CompletedAt = null, - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), - IsActive = true - } - ); - - modelBuilder.Entity().HasData( - new Order - { - Id = Order1Id, - FK_SaleId = Sale1Id, - OrderDate = new DateTime(2026, 8, 25, 9, 0, 0), - FK_StoreId = MasterDataSeed.FortStoreId, - TotalAmount = 3000m, - Status = OrderStatus.Fulfilled, + Status = ShopPOStatus.Fulfilled, + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0), + ConfirmedBy = MasterDataSeed.Supervisor1UserId, FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0), CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, - new Order + new ShopPO { - Id = Order2Id, - FK_SaleId = Sale2Id, - OrderDate = new DateTime(2026, 8, 30, 10, 0, 0), + Id = ShopPO2Id, FK_StoreId = MasterDataSeed.KandyStoreId, + RaisedById = MasterDataSeed.SalesRep2UserId, + InvoiceId = null, TotalAmount = 1200m, - Status = OrderStatus.Pending, + Status = ShopPOStatus.Pending, + ConfirmedAt = null, + ConfirmedBy = null, FulfilledAt = null, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true + }, + new ShopPO + { + Id = ShopPO3Id, + FK_StoreId = MasterDataSeed.KandyStoreId, + RaisedById = MasterDataSeed.SalesRep2UserId, + InvoiceId = Invoice2Id, + TotalAmount = 2400m, + Status = ShopPOStatus.Fulfilled, + ConfirmedAt = new DateTime(2026, 8, 31, 8, 30, 0), + ConfirmedBy = MasterDataSeed.Supervisor1UserId, + FulfilledAt = new DateTime(2026, 8, 31, 13, 0, 0), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0), + IsActive = true } ); - modelBuilder.Entity().HasData( - new OrderItem { Id = OrderItem1Id, FK_OrderId = Order1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, Quantity = 30, QuantityFulfilled = 30, UnitPrice = 60m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, - new OrderItem { Id = OrderItem2Id, FK_OrderId = Order1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, Quantity = 24, QuantityFulfilled = 24, UnitPrice = 50m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, - new OrderItem { Id = OrderItem3Id, FK_OrderId = Order2Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 10, QuantityFulfilled = 0, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true } + modelBuilder.Entity().HasData( + new ShopPOItem { Id = ShopPOItem1Id, FK_ShopPOId = ShopPO1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, Quantity = 30, QuantityFulfilled = 30, UnitPrice = 60m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, + new ShopPOItem { Id = ShopPOItem2Id, FK_ShopPOId = ShopPO1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, Quantity = 24, QuantityFulfilled = 24, UnitPrice = 50m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, + new ShopPOItem { Id = ShopPOItem3Id, FK_ShopPOId = ShopPO2Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 10, QuantityFulfilled = 0, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true }, + new ShopPOItem { Id = ShopPOItem4Id, FK_ShopPOId = ShopPO3Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 20, QuantityFulfilled = 20, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0), IsActive = true } + ); + + modelBuilder.Entity().HasData( + new Invoice + { + Id = Invoice1Id, + FK_ShopPOId = ShopPO1Id, + Status = InvoiceStatus.Finalized, + PaymentStatus = PaymentStatus.Paid, + CreatedBy = MasterDataSeed.SalesRep1UserId, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0), + PrintedBy = MasterDataSeed.SalesRep1UserId, + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0), + FinalizedBy = MasterDataSeed.Supervisor1UserId, + TotalAmount = 3000m, + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0), + IsActive = true + }, + new Invoice + { + Id = Invoice2Id, + FK_ShopPOId = ShopPO3Id, + Status = InvoiceStatus.Printed, + PaymentStatus = PaymentStatus.PartiallyPaid, + CreatedBy = MasterDataSeed.SalesRep2UserId, + PrintedAt = new DateTime(2026, 8, 31, 9, 15, 0), + PrintedBy = MasterDataSeed.SalesRep2UserId, + FinalizedAt = null, + FinalizedBy = null, + TotalAmount = 2400m, + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0), + IsActive = true + } ); modelBuilder.Entity().HasData( @@ -135,20 +151,19 @@ public static class OperationsDataSeed { Id = LoadingSheet1Id, FK_RideId = ClosedSaleRunId, - FK_SourceWarehouseId = MasterDataSeed.ColomboWarehouseId, - Status = LoadingSheetStatus.ReceiptConfirmed, - DispatchConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0), - DispatchConfirmedBy = MasterDataSeed.Supervisor1UserId, - ReceiptConfirmedAt = new DateTime(2026, 8, 25, 14, 5, 0), - ReceiptConfirmedBy = MasterDataSeed.Driver1UserId, + Status = LoadingSheetStatus.Confirmed, + PopulatedBy = MasterDataSeed.Supervisor1UserId, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0), + ConfirmedBy = MasterDataSeed.Supervisor1UserId, CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true } ); modelBuilder.Entity().HasData( - new LoadingSheetItem { Id = LoadingSheetItem1Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, QuantityDispatched = 50m, QuantityReceived = 50m, QuantityResolved = null }, - new LoadingSheetItem { Id = LoadingSheetItem2Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, QuantityDispatched = 30m, QuantityReceived = 30m, QuantityResolved = null } + new LoadingSheetItem { Id = LoadingSheetItem1Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, FK_WarehouseId = MasterDataSeed.ColomboWarehouseId, QuantityDispatched = 50m, CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true }, + new LoadingSheetItem { Id = LoadingSheetItem2Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, FK_WarehouseId = MasterDataSeed.ColomboWarehouseId, QuantityDispatched = 30m, CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true } ); modelBuilder.Entity().HasData( @@ -156,7 +171,7 @@ public static class OperationsDataSeed { Id = DeliveryTask1Id, FK_RideId = ActiveDeliveryRunId, - FK_OrderId = Order2Id, + FK_ShopPOId = ShopPO2Id, Sequence = 1, Status = DeliveryTaskStatus.Pending, CustomerConfirmed = false, diff --git a/Distribution/Data/Seed/OperationsExtrasSeed.cs b/Distribution/Data/Seed/OperationsExtrasSeed.cs index 6ff35a8..db3f318 100644 --- a/Distribution/Data/Seed/OperationsExtrasSeed.cs +++ b/Distribution/Data/Seed/OperationsExtrasSeed.cs @@ -32,8 +32,6 @@ public static class OperationsExtrasSeed private static readonly Guid DriverComplianceConfig1Id = new("64000000-0000-0000-0000-000000000001"); - private static readonly Guid RideCancelRequest1Id = new("65000000-0000-0000-0000-000000000001"); - private static readonly Guid RouteVisitLog1Id = new("66000000-0000-0000-0000-000000000001"); private static readonly Guid RouteVisitLog2Id = new("66000000-0000-0000-0000-000000000002"); @@ -95,21 +93,6 @@ public static class OperationsExtrasSeed new DriverComplianceConfig { Id = DriverComplianceConfig1Id, EnforceLicenseExpiry = true, EnforceMedicalClearance = true, UpdatedAt = new DateTime(2026, 8, 20), UpdatedBy = MasterDataSeed.Supervisor1UserId } ); - modelBuilder.Entity().HasData( - new RideCancelRequest - { - Id = RideCancelRequest1Id, - FK_RideId = OperationsDataSeed.ActiveDeliveryRunId, - TypeCode = CancelRequestType.VehicleBreakdown, - Reason = "Reported minor engine issue, resolved after inspection", - RequestedBy = MasterDataSeed.Driver2UserId, - RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0), - Status = CancelRequestStatus.Rejected, - ApprovedBy = MasterDataSeed.Supervisor1UserId, - ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0) - } - ); - modelBuilder.Entity().HasData( new RouteVisitLog { Id = RouteVisitLog1Id, FK_RouteId = MasterDataSeed.ColomboRouteId, FK_StoreId = MasterDataSeed.FortStoreId, FK_UserId = MasterDataSeed.SalesRep1UserId, CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0), CheckInLatitude = 6.9344m, CheckInLongitude = 79.8428m, IsDeviationFlagged = false, CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0), CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, new RouteVisitLog { Id = RouteVisitLog2Id, FK_RouteId = MasterDataSeed.ColomboRouteId, FK_StoreId = MasterDataSeed.DehiwalaStoreId, FK_UserId = MasterDataSeed.SalesRep1UserId, CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0), CheckInLatitude = 6.9000m, CheckInLongitude = 79.8654m, IsDeviationFlagged = true, CheckOutAt = null, CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0), IsActive = true } diff --git a/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs b/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs index fd8a1ab..9fbe5e1 100644 --- a/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs +++ b/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs @@ -1,4 +1,4 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.DeliveryRide; @@ -7,7 +7,7 @@ public record DeliveryTaskItemResponse(Guid ItemId, string ItemName, int Quantit public record DeliveryTaskResponse( Guid Id, Guid FK_RideId, - Guid FK_OrderId, + Guid FK_ShopPOId, Guid StoreId, string StoreName, int Sequence, diff --git a/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs b/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs index 3e7aea7..e096063 100644 --- a/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs +++ b/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs @@ -1,4 +1,4 @@ -using Distribution.Data; +using Distribution.Data; using Distribution.Models; using Microsoft.EntityFrameworkCore; @@ -8,27 +8,27 @@ public class DeliveryTaskRepository(AppDBContext context) : IDeliveryTaskReposit { public async Task GetByIdAsync(Guid id) => await context.DeliveryTasks - .Include(t => t.Order) + .Include(t => t.ShopPO) .ThenInclude(o => o.Store) - .Include(t => t.Order) - .ThenInclude(o => o.OrderItems) + .Include(t => t.ShopPO) + .ThenInclude(o => o.Items.Where(i => i.IsActive)) .ThenInclude(i => i.Item) .FirstOrDefaultAsync(t => t.Id == id); public async Task> GetByRideIdAsync(Guid rideId) => await context.DeliveryTasks - .Include(t => t.Order) + .Include(t => t.ShopPO) .ThenInclude(o => o.Store) - .Include(t => t.Order) - .ThenInclude(o => o.OrderItems) + .Include(t => t.ShopPO) + .ThenInclude(o => o.Items.Where(i => i.IsActive)) .ThenInclude(i => i.Item) .Where(t => t.FK_RideId == rideId) .OrderBy(t => t.Sequence) .ToListAsync(); - public async Task ExistsForOrderAndRideAsync(Guid orderId, Guid rideId) => + public async Task ExistsForOrderAndRideAsync(Guid shopPOId, Guid rideId) => await context.DeliveryTasks - .AnyAsync(t => t.FK_OrderId == orderId && t.FK_RideId == rideId); + .AnyAsync(t => t.FK_ShopPOId == shopPOId && t.FK_RideId == rideId); public async Task AddAsync(DeliveryTask task) => await context.DeliveryTasks.AddAsync(task); diff --git a/Distribution/Features/DeliveryRide/DeliveryTaskService.cs b/Distribution/Features/DeliveryRide/DeliveryTaskService.cs index 265ef1f..5f1f336 100644 --- a/Distribution/Features/DeliveryRide/DeliveryTaskService.cs +++ b/Distribution/Features/DeliveryRide/DeliveryTaskService.cs @@ -1,6 +1,5 @@ -using Distribution.Features.Order; using Distribution.Features.Ride; -using Distribution.Features.Sale; +using Distribution.Features.ShopPO; using Distribution.Features.Stock; using Distribution.Infra.UoW; using Distribution.Models; @@ -10,23 +9,22 @@ namespace Distribution.Features.DeliveryRide; public class DeliveryTaskService( IDeliveryTaskRepository repo, IRideRepository rideRepo, - IOrderRepository orderRepo, - ISaleRepository saleRepo, + IShopPORepository shopPORepo, IStockRepository stockRepo, IUnitOfWork uow) { private static DeliveryTaskResponse ToResponse(DeliveryTask t) => new(t.Id, t.FK_RideId, - t.FK_OrderId, - t.Order.FK_StoreId, - t.Order.Store?.StoreName ?? string.Empty, + t.FK_ShopPOId, + t.ShopPO.FK_StoreId, + t.ShopPO.Store?.StoreName ?? string.Empty, t.Sequence, t.Status, t.CustomerConfirmed, t.ConfirmedAt, t.Note, - t.Order.OrderItems.Select(i => new DeliveryTaskItemResponse( + t.ShopPO.Items.Select(i => new DeliveryTaskItemResponse( i.FK_ItemId, i.Item?.Name ?? string.Empty, i.Quantity, @@ -34,52 +32,8 @@ public class DeliveryTaskService( i.UnitPrice)).ToList(), t.CreatedAt); - public async Task> GenerateAsync(Guid rideId, CancellationToken ct = default) - { - var ride = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.Active) - throw new InvalidOperationException("Tasks can only be generated for an Active ride"); - - if (ride.RideType != RideType.Delivery) - throw new InvalidOperationException("Tasks can only be generated for a Delivery ride"); - - var orders = await orderRepo.GetPendingByRouteIdAsync(ride.FK_RouteId); - - var created = new List(); - int sequence = 1; - - foreach (var order in orders) - { - if (await repo.ExistsForOrderAndRideAsync(order.Id, rideId)) - continue; - - var task = new DeliveryTask - { - FK_RideId = rideId, - FK_OrderId = order.Id, - Sequence = sequence++, - Status = DeliveryTaskStatus.Pending - }; - created.Add(task); - } - - if (created.Count == 0) - return new List(); - - await uow.BeginAsync(ct); - try - { - foreach (var task in created) - await repo.AddAsync(task); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - var saved = await repo.GetByRideIdAsync(rideId); - return saved.Select(ToResponse).ToList(); - } + public Task> GenerateAsync(Guid rideId, CancellationToken ct = default) => + throw new NotImplementedException("Delivery task auto-generation is deferred — route-based dispatch not yet implemented."); public async Task> GetByRideIdAsync(Guid rideId) { @@ -103,16 +57,16 @@ public class DeliveryTaskService( foreach (var input in request.Items) { - var orderItem = task.Order.OrderItems.FirstOrDefault(i => i.FK_ItemId == input.ItemId) - ?? throw new InvalidOperationException($"Item {input.ItemId} is not on this order"); + var shopPOItem = task.ShopPO.Items.FirstOrDefault(i => i.FK_ItemId == input.ItemId) + ?? throw new InvalidOperationException($"Item {input.ItemId} is not on this ShopPO"); if (input.QuantityFulfilled < 0) throw new InvalidOperationException($"QuantityFulfilled cannot be negative for item {input.ItemId}"); - if (input.QuantityFulfilled > orderItem.Quantity) + if (input.QuantityFulfilled > shopPOItem.Quantity) throw new InvalidOperationException($"QuantityFulfilled exceeds ordered quantity for item {input.ItemId}"); - orderItem.QuantityFulfilled = input.QuantityFulfilled; + shopPOItem.QuantityFulfilled = input.QuantityFulfilled; } await uow.BeginAsync(ct); @@ -135,7 +89,7 @@ public class DeliveryTaskService( if (task.Status != DeliveryTaskStatus.Pending) throw new InvalidOperationException("Only a Pending task can be confirmed"); - if (!task.Order.OrderItems.Any(i => i.QuantityFulfilled > 0)) + if (!task.ShopPO.Items.Any(i => i.QuantityFulfilled > 0)) throw new InvalidOperationException("Set quantities before confirming — at least one item must have a fulfilled quantity greater than zero"); var ride = await rideRepo.GetByIdAsync(task.FK_RideId) @@ -143,21 +97,21 @@ public class DeliveryTaskService( var vehicleId = ride.FK_VehicleId; - bool fullyDelivered = task.Order.OrderItems.All(i => i.QuantityFulfilled == i.Quantity); + bool fullyDelivered = task.ShopPO.Items.All(i => i.QuantityFulfilled == i.Quantity); task.CustomerConfirmed = true; task.ConfirmedAt = DateTime.Now; task.Status = fullyDelivered ? DeliveryTaskStatus.Delivered : DeliveryTaskStatus.PartiallyDelivered; - var order = task.Order; - order.Status = fullyDelivered ? OrderStatus.Fulfilled : OrderStatus.PartiallyFulfilled; + var shopPO = task.ShopPO; + shopPO.Status = fullyDelivered ? ShopPOStatus.Fulfilled : ShopPOStatus.PartiallyFulfilled; if (fullyDelivered) - order.FulfilledAt = DateTime.Now; + shopPO.FulfilledAt = DateTime.Now; await uow.BeginAsync(ct); try { - foreach (var item in task.Order.OrderItems.Where(i => i.QuantityFulfilled > 0)) + foreach (var item in task.ShopPO.Items.Where(i => i.QuantityFulfilled > 0)) { var vehicleBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId); var availableQuantity = vehicleBalance?.Quantity ?? 0; @@ -180,21 +134,12 @@ public class DeliveryTaskService( ToLocationType = LocationType.External, Quantity = item.QuantityFulfilled, Type = MovementType.Sale, - ReferenceId = task.FK_OrderId + ReferenceId = task.FK_ShopPOId }); } repo.Update(task); - orderRepo.Update(order); - - if (fullyDelivered) - { - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId) - ?? throw new KeyNotFoundException("Sale not found"); - sale.Status = SaleStatus.Completed; - sale.CompletedAt = DateTime.Now; - saleRepo.Update(sale); - } + shopPORepo.Update(shopPO); await uow.CommitAsync(ct); } diff --git a/Distribution/Features/Invoice/IInvoiceRepository.cs b/Distribution/Features/Invoice/IInvoiceRepository.cs new file mode 100644 index 0000000..c4dc6ad --- /dev/null +++ b/Distribution/Features/Invoice/IInvoiceRepository.cs @@ -0,0 +1,13 @@ +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +public interface IInvoiceRepository +{ + Task GetByIdAsync(Guid id); + Task GetByShopPOIdAsync(Guid shopPOId); + Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize); + Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status); + Task AddAsync(Models.Invoice invoice); + void Update(Models.Invoice invoice); +} diff --git a/Distribution/Features/Invoice/InvoiceController.cs b/Distribution/Features/Invoice/InvoiceController.cs new file mode 100644 index 0000000..5060dcf --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceController.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Mvc; +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +[ApiController] +[Route("api/invoices")] +public class InvoiceController(InvoiceService service) : ControllerBase +{ + [HttpGet] + public async Task GetAll( + [FromQuery] Guid? agentId, + [FromQuery] Guid? routeId, + [FromQuery] Guid? shopId, + [FromQuery] InvoiceStatus? status, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20) + { + var result = await service.GetAllAsync(agentId, routeId, shopId, status, page, pageSize); + return Ok(result); + } + + [HttpGet("{id:guid}")] + public async Task GetById(Guid id) + { + var result = await service.GetByIdAsync(id); + return result is null ? NotFound() : Ok(result); + } +} diff --git a/Distribution/Features/Invoice/InvoiceDTOs.cs b/Distribution/Features/Invoice/InvoiceDTOs.cs new file mode 100644 index 0000000..dd1b413 --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceDTOs.cs @@ -0,0 +1,22 @@ +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +public record CreateInvoiceRequest(Guid ShopPOId); +public record InvoiceItemAdjustment(Guid ShopPOItemId, int AdjustedQuantity, string? Note = null); +public record FinalizeInvoiceRequest(List Adjustments); + +public record InvoiceResponse( + Guid Id, + Guid ShopPOId, + string StoreName, + InvoiceStatus Status, + PaymentStatus PaymentStatus, + Guid CreatedBy, + DateTime? PrintedAt, + Guid? PrintedBy, + DateTime? FinalizedAt, + Guid? FinalizedBy, + decimal TotalAmount, + bool IsActive, + DateTime CreatedAt); diff --git a/Distribution/Features/Invoice/InvoiceRepository.cs b/Distribution/Features/Invoice/InvoiceRepository.cs new file mode 100644 index 0000000..72faf5f --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceRepository.cs @@ -0,0 +1,47 @@ +using Distribution.Data; +using Distribution.Models; +using Microsoft.EntityFrameworkCore; + +namespace Distribution.Features.Invoice; + +public class InvoiceRepository(AppDBContext context) : IInvoiceRepository +{ + public async Task GetByIdAsync(Guid id) => + await context.Invoices + .Include(i => i.ShopPO).ThenInclude(p => p.Store) + .Include(i => i.Payments.Where(p => p.IsActive)) + .FirstOrDefaultAsync(i => i.Id == id && i.IsActive); + + public async Task GetByShopPOIdAsync(Guid shopPOId) => + await context.Invoices + .Include(i => i.ShopPO) + .FirstOrDefaultAsync(i => i.FK_ShopPOId == shopPOId && i.IsActive); + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize) => + await context.Invoices + .Include(i => i.ShopPO).ThenInclude(p => p.Store) + .Where(i => i.IsActive + && (agentId == null || i.ShopPO.RaisedById == agentId) + && (routeId == null || i.ShopPO.Store.FK_RouteId == routeId) + && (shopId == null || i.ShopPO.FK_StoreId == shopId) + && (status == null || i.Status == status)) + .OrderByDescending(i => i.CreatedAt) + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + public async Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status) => + await context.Invoices + .Include(i => i.ShopPO).ThenInclude(p => p.Store) + .CountAsync(i => i.IsActive + && (agentId == null || i.ShopPO.RaisedById == agentId) + && (routeId == null || i.ShopPO.Store.FK_RouteId == routeId) + && (shopId == null || i.ShopPO.FK_StoreId == shopId) + && (status == null || i.Status == status)); + + public async Task AddAsync(Models.Invoice invoice) => + await context.Invoices.AddAsync(invoice); + + public void Update(Models.Invoice invoice) => + context.Invoices.Update(invoice); +} diff --git a/Distribution/Features/Invoice/InvoiceService.cs b/Distribution/Features/Invoice/InvoiceService.cs new file mode 100644 index 0000000..51e20f1 --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceService.cs @@ -0,0 +1,33 @@ +using Distribution.Features.Stock; +using Distribution.Infra.Authorization; +using Distribution.Infra.UoW; +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +public class InvoiceService( + IInvoiceRepository repo, + IUnitOfWork uow, + ICurrentUserService currentUser) +{ + private static InvoiceResponse ToResponse(Models.Invoice i) => + new(i.Id, i.FK_ShopPOId, + i.ShopPO?.Store?.StoreName ?? string.Empty, + i.Status, i.PaymentStatus, i.CreatedBy, + i.PrintedAt, i.PrintedBy, + i.FinalizedAt, i.FinalizedBy, + i.TotalAmount, i.IsActive, i.CreatedAt); + + public async Task GetByIdAsync(Guid id) + { + var invoice = await repo.GetByIdAsync(id); + return invoice is null ? null : ToResponse(invoice); + } + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize) + { + var total = await repo.GetCountAsync(agentId, routeId, shopId, status); + var items = await repo.GetAllAsync(agentId, routeId, shopId, status, page, pageSize); + return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); + } +} diff --git a/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs b/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs index 3e3cf52..44c24bf 100644 --- a/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs +++ b/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs @@ -8,7 +8,6 @@ public interface ILoadingSheetRepository Task GetActiveByRideIdAsync(Guid rideId); Task> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, int page, int pageSize); Task GetCountAsync(Guid? rideId, LoadingSheetStatus? status); - Task> GetAggregatedOrderItemsByRouteIdAsync(Guid routeId); Task AddAsync(LoadingSheet sheet); void Update(LoadingSheet sheet); void RemoveItems(IEnumerable items); diff --git a/Distribution/Features/LoadingEvent/LoadingSheetController.cs b/Distribution/Features/LoadingEvent/LoadingSheetController.cs index 3d233ae..2c8ec3d 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetController.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetController.cs @@ -1,4 +1,4 @@ -using Distribution.Models; +using Distribution.Models; using Distribution.Infra.Authorization; using Microsoft.AspNetCore.Mvc; @@ -29,9 +29,10 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer [HttpPost] public async Task Create(CreateLoadingSheetRequest request, CancellationToken ct) { + var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); try { - var result = await service.CreateAsync(request, ct); + var result = await service.CreateAsync(request, userId, ct); return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); } catch (KeyNotFoundException) { return NotFound(); } @@ -50,90 +51,13 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - [HttpPost("{id:guid}/confirm-dispatch")] - public async Task ConfirmDispatch(Guid id, CancellationToken ct) + [HttpPost("{id:guid}/confirm")] + public async Task Confirm(Guid id, CancellationToken ct) { var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); try { - var result = await service.ConfirmDispatchAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPut("{id:guid}/receipt-items")] - public async Task SetReceiptItems(Guid id, SetReceiptItemsRequest request, CancellationToken ct) - { - try - { - var result = await service.SetReceiptItemsAsync(id, request, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPost("{id:guid}/confirm-receipt")] - public async Task ConfirmReceipt(Guid id, ConfirmReceiptRequest request, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ConfirmReceiptAsync(id, request, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPost("{id:guid}/resolve")] - public async Task Resolve(Guid id, ResolveDiscrepancyRequest request, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ResolveAsync(id, request, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/dispatch")] - public async Task PatchDispatch(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ConfirmDispatchAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/receipt")] - public async Task PatchReceipt(Guid id, PatchReceiptRequest request, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.PatchReceiptAsync(id, request.Items, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/resolve")] - public async Task PatchResolve(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.PatchResolveAsync(id, userId, ct); + var result = await service.ConfirmAsync(id, userId, ct); return Ok(result); } catch (KeyNotFoundException) { return NotFound(); } diff --git a/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs b/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs index ae2e0d6..cbd9a23 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs @@ -5,37 +5,27 @@ namespace Distribution.Features.LoadingEvent; public record LoadingSheetResponse( Guid Id, Guid FK_RideId, - Guid FK_SourceWarehouseId, - string WarehouseName, LoadingSheetStatus Status, - DateTime? DispatchConfirmedAt, - Guid? DispatchConfirmedBy, - DateTime? ReceiptConfirmedAt, - Guid? ReceiptConfirmedBy, + Guid PopulatedBy, + DateTime PopulatedAt, + DateTime? ConfirmedAt, + Guid? ConfirmedBy, DateTime CreatedAt, - List Items); + List Items, + List Orders); public record LoadingSheetItemResponse( Guid Id, Guid FK_ItemId, string ItemName, + Guid FK_WarehouseId, + string WarehouseName, decimal QuantityDispatched, - decimal? QuantityReceived, - decimal? QuantityResolved); + Guid? FK_ShopPOItemId); + +public record LoadingSheetOrderResponse(Guid ShopPOId); public record CreateLoadingSheetRequest(Guid FK_RideId); public record SetItemsRequest(List Items); -public record SetItemInput(Guid FK_ItemId, decimal Quantity); - -public record SetReceiptItemsRequest(List Items); -public record ReceiptItemInput(Guid FK_ItemId, decimal QuantityReceived); - -public record ConfirmReceiptRequest(int Meterstart); - -public record ResolveDiscrepancyRequest(List Items, int Meterstart); -public record ResolveItemInput(Guid FK_ItemId, decimal QuantityResolved); - -// Combined PATCH endpoints used by the frontend -public record PatchReceiptItemInput(Guid ItemId, decimal QuantityReceived); -public record PatchReceiptRequest(List Items); +public record SetItemInput(Guid FK_ItemId, Guid FK_WarehouseId, decimal Quantity, Guid? FK_ShopPOItemId = null); diff --git a/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs b/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs index bb6c404..b4080e4 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs @@ -8,20 +8,20 @@ public class LoadingSheetRepository(AppDBContext context) : ILoadingSheetReposit { public async Task GetByIdAsync(Guid id) => await context.LoadingSheets - .Include(s => s.SourceWarehouse) .Include(s => s.Items).ThenInclude(i => i.Item) + .Include(s => s.Items).ThenInclude(i => i.Warehouse) + .Include(s => s.Orders) .FirstOrDefaultAsync(s => s.Id == id); public async Task GetActiveByRideIdAsync(Guid rideId) => await context.LoadingSheets - .FirstOrDefaultAsync(s => - s.FK_RideId == rideId && - s.Status != LoadingSheetStatus.ReceiptConfirmed && - s.Status != LoadingSheetStatus.Resolved); + .FirstOrDefaultAsync(s => s.FK_RideId == rideId && s.Status == LoadingSheetStatus.Planned); public async Task> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, int page, int pageSize) => await context.LoadingSheets - .Include(s => s.SourceWarehouse) + .Include(s => s.Items).ThenInclude(i => i.Item) + .Include(s => s.Items).ThenInclude(i => i.Warehouse) + .Include(s => s.Orders) .Where(s => (rideId == null || s.FK_RideId == rideId) && (status == null || s.Status == status)) @@ -36,19 +36,6 @@ public class LoadingSheetRepository(AppDBContext context) : ILoadingSheetReposit (rideId == null || s.FK_RideId == rideId) && (status == null || s.Status == status)); - public async Task> GetAggregatedOrderItemsByRouteIdAsync(Guid routeId) - { - var groups = await context.OrderItems - .Where(oi => oi.IsActive - && oi.Order.IsActive - && oi.Order.Store.FK_RouteId == routeId - && (oi.Order.Status == OrderStatus.Pending || oi.Order.Status == OrderStatus.PartiallyFulfilled)) - .GroupBy(oi => oi.FK_ItemId) - .Select(g => new { ItemId = g.Key, TotalQty = g.Sum(oi => (decimal)(oi.Quantity - oi.QuantityFulfilled)) }) - .ToListAsync(); - return groups.Select(x => (x.ItemId, x.TotalQty)).ToList(); - } - public async Task AddAsync(LoadingSheet sheet) => await context.LoadingSheets.AddAsync(sheet); diff --git a/Distribution/Features/LoadingEvent/LoadingSheetService.cs b/Distribution/Features/LoadingEvent/LoadingSheetService.cs index dadcc42..a37d1e1 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetService.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetService.cs @@ -24,7 +24,7 @@ public class LoadingSheetService( return sheet is null ? null : ToResponse(sheet); } - public async Task CreateAsync(CreateLoadingSheetRequest request, CancellationToken ct = default) + public async Task CreateAsync(CreateLoadingSheetRequest request, Guid userId, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(request.FK_RideId) ?? throw new KeyNotFoundException("Ride not found"); @@ -34,22 +34,16 @@ public class LoadingSheetService( var existing = await repo.GetActiveByRideIdAsync(request.FK_RideId); if (existing is not null) - throw new InvalidOperationException("This ride already has an active loading sheet"); + throw new InvalidOperationException("This ride already has a Planned loading sheet"); var sheet = new LoadingSheet { FK_RideId = ride.Id, - FK_SourceWarehouseId = ride.FK_SourceWarehouseId, - Status = LoadingSheetStatus.Pending + Status = LoadingSheetStatus.Planned, + PopulatedBy = userId, + PopulatedAt = DateTime.Now }; - if (ride.RideType == RideType.Delivery) - { - var orderItems = await repo.GetAggregatedOrderItemsByRouteIdAsync(ride.FK_RouteId); - foreach (var (itemId, qty) in orderItems) - sheet.Items.Add(new LoadingSheetItem { FK_ItemId = itemId, QuantityDispatched = qty }); - } - await uow.BeginAsync(ct); try { @@ -67,8 +61,8 @@ public class LoadingSheetService( var sheet = await repo.GetByIdAsync(id) ?? throw new KeyNotFoundException("Loading sheet not found"); - if (sheet.Status != LoadingSheetStatus.Pending) - throw new InvalidOperationException("Items can only be changed while the sheet is Pending"); + if (sheet.Status != LoadingSheetStatus.Planned) + throw new InvalidOperationException("Items can only be changed while the sheet is Planned"); await uow.BeginAsync(ct); try @@ -78,6 +72,8 @@ public class LoadingSheetService( { FK_LoadingSheetId = sheet.Id, FK_ItemId = i.FK_ItemId, + FK_WarehouseId = i.FK_WarehouseId, + FK_ShopPOItemId = i.FK_ShopPOItemId, QuantityDispatched = i.Quantity })); await uow.CommitAsync(ct); @@ -88,289 +84,91 @@ public class LoadingSheetService( return ToResponse(saved!); } - public async Task ConfirmDispatchAsync(Guid id, Guid userId, CancellationToken ct = default) + public async Task ConfirmAsync(Guid id, Guid userId, CancellationToken ct = default) { var sheet = await repo.GetByIdAsync(id) ?? throw new KeyNotFoundException("Loading sheet not found"); - if (sheet.Status != LoadingSheetStatus.Pending) - throw new InvalidOperationException($"Cannot confirm dispatch for a sheet in {sheet.Status} status"); + if (sheet.Status != LoadingSheetStatus.Planned) + throw new InvalidOperationException($"Cannot confirm a sheet in {sheet.Status} status"); if (!sheet.Items.Any(i => i.QuantityDispatched > 0)) throw new InvalidOperationException("Sheet must have at least one item with quantity greater than zero"); - sheet.Status = LoadingSheetStatus.DispatchConfirmed; - sheet.DispatchConfirmedAt = DateTime.Now; - sheet.DispatchConfirmedBy = userId; - - await uow.BeginAsync(ct); - try { repo.Update(sheet); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task SetReceiptItemsAsync(Guid id, SetReceiptItemsRequest request, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DispatchConfirmed) - throw new InvalidOperationException("Receipt quantities can only be set after dispatch is confirmed"); - - foreach (var input in request.Items) - { - var item = sheet.Items.FirstOrDefault(i => i.FK_ItemId == input.FK_ItemId) - ?? throw new InvalidOperationException($"Item {input.FK_ItemId} is not on this loading sheet"); - item.QuantityReceived = input.QuantityReceived; - } - - await uow.BeginAsync(ct); - try { repo.Update(sheet); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task ConfirmReceiptAsync(Guid id, ConfirmReceiptRequest request, Guid userId, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DispatchConfirmed) - throw new InvalidOperationException($"Cannot confirm receipt for a sheet in {sheet.Status} status"); - - if (sheet.Items.Any(i => !i.QuantityReceived.HasValue)) - throw new InvalidOperationException("All items must have a received quantity before confirming receipt"); - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) ?? throw new KeyNotFoundException("Ride not found"); - var hasDiscrepancy = sheet.Items.Any(i => i.QuantityReceived != i.QuantityDispatched); - await uow.BeginAsync(ct); try { - if (hasDiscrepancy) - { - sheet.Status = LoadingSheetStatus.DiscrepancyFlagged; - } - else - { - sheet.Status = LoadingSheetStatus.ReceiptConfirmed; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; + await ApplyLoadMovementsAsync(sheet.Id, ride.FK_VehicleId, sheet.Items, userId); - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityReceived!.Value)).ToList(); - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = request.Meterstart; - rideRepo.Update(ride); - } + sheet.Status = LoadingSheetStatus.Confirmed; + sheet.ConfirmedAt = DateTime.Now; + sheet.ConfirmedBy = userId; repo.Update(sheet); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } - return ToResponse(sheet); + var saved = await repo.GetByIdAsync(id); + return ToResponse(saved!); } - public async Task ResolveAsync(Guid id, ResolveDiscrepancyRequest request, Guid userId, CancellationToken ct = default) + private async Task ApplyLoadMovementsAsync(Guid sheetId, Guid vehicleId, List items, Guid userId) { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DiscrepancyFlagged) - throw new InvalidOperationException($"Cannot resolve a sheet in {sheet.Status} status"); - - foreach (var input in request.Items) + foreach (var item in items.Where(i => i.QuantityDispatched > 0)) { - var item = sheet.Items.FirstOrDefault(i => i.FK_ItemId == input.FK_ItemId) - ?? throw new InvalidOperationException($"Item {input.FK_ItemId} is not on this loading sheet"); - if (input.QuantityResolved < 0) - throw new InvalidOperationException("Resolved quantity cannot be negative"); - item.QuantityResolved = input.QuantityResolved; - } + var warehouseBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, item.FK_WarehouseId) + ?? throw new InvalidOperationException($"No stock found in warehouse for item {item.FK_ItemId}"); - if (sheet.Items.Any(i => !i.QuantityResolved.HasValue)) - throw new InvalidOperationException("All items must have a resolved quantity"); + if (warehouseBalance.Quantity < item.QuantityDispatched) + throw new InvalidOperationException($"Insufficient warehouse stock for item {item.FK_ItemId}"); - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - sheet.Status = LoadingSheetStatus.Resolved; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; - - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityResolved!.Value)).ToList(); - - await uow.BeginAsync(ct); - try - { - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = request.Meterstart; - rideRepo.Update(ride); - - repo.Update(sheet); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task PatchReceiptAsync(Guid id, List items, Guid userId, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DispatchConfirmed) - throw new InvalidOperationException($"Cannot set receipt for a sheet in {sheet.Status} status"); - - foreach (var input in items) - { - var sheetItem = sheet.Items.FirstOrDefault(i => i.FK_ItemId == input.ItemId) - ?? throw new InvalidOperationException($"Item {input.ItemId} is not on this loading sheet"); - sheetItem.QuantityReceived = input.QuantityReceived; - } - - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - var hasDiscrepancy = sheet.Items.Any(i => i.QuantityReceived != i.QuantityDispatched); - - await uow.BeginAsync(ct); - try - { - if (hasDiscrepancy) - { - sheet.Status = LoadingSheetStatus.DiscrepancyFlagged; - } - else - { - sheet.Status = LoadingSheetStatus.ReceiptConfirmed; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; - - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityReceived!.Value)).ToList(); - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = 0; - rideRepo.Update(ride); - } - - repo.Update(sheet); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task PatchResolveAsync(Guid id, Guid userId, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DiscrepancyFlagged) - throw new InvalidOperationException($"Cannot resolve a sheet in {sheet.Status} status"); - - foreach (var item in sheet.Items) - { - if (!item.QuantityReceived.HasValue) - throw new InvalidOperationException($"Item {item.FK_ItemId} has no received quantity to resolve from"); - item.QuantityResolved = item.QuantityReceived.Value; - } - - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - sheet.Status = LoadingSheetStatus.Resolved; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; - - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityResolved!.Value)).ToList(); - - await uow.BeginAsync(ct); - try - { - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = 0; - rideRepo.Update(ride); - - repo.Update(sheet); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - private async Task ApplyLoadMovementsAsync(LoadingSheet sheet, Guid vehicleId, List<(Guid ItemId, decimal Qty)> lines, Guid userId) - { - foreach (var (itemId, qty) in lines.Where(l => l.Qty > 0)) - { - var warehouseBalance = await stockRepo.GetBalanceAsync(itemId, sheet.FK_SourceWarehouseId) - ?? throw new InvalidOperationException($"No stock found in warehouse for item {itemId}"); - if (warehouseBalance.Quantity < qty) - throw new InvalidOperationException($"Insufficient warehouse stock for item {itemId}"); - - warehouseBalance.Quantity -= qty; + warehouseBalance.Quantity -= item.QuantityDispatched; warehouseBalance.UpdatedAt = DateTime.Now; stockRepo.UpdateBalance(warehouseBalance); - var vehicleBalance = await stockRepo.GetBalanceAsync(itemId, vehicleId); + var vehicleBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId); if (vehicleBalance is null) { await stockRepo.AddBalanceAsync(new StockBalance { - FK_ItemId = itemId, + FK_ItemId = item.FK_ItemId, LocationId = vehicleId, LocationType = LocationType.Vehicle, - Quantity = qty + Quantity = item.QuantityDispatched }); } else { - vehicleBalance.Quantity += qty; + vehicleBalance.Quantity += item.QuantityDispatched; vehicleBalance.UpdatedAt = DateTime.Now; stockRepo.UpdateBalance(vehicleBalance); } await stockRepo.AddMovementAsync(new StockMovement { - FK_ItemId = itemId, - FromLocationId = sheet.FK_SourceWarehouseId, + FK_ItemId = item.FK_ItemId, + FromLocationId = item.FK_WarehouseId, FromLocationType = LocationType.Warehouse, ToLocationId = vehicleId, ToLocationType = LocationType.Vehicle, - Quantity = qty, + Quantity = item.QuantityDispatched, Type = MovementType.Load, - ReferenceId = sheet.Id, + ReferenceId = sheetId, CreatedBy = userId }); } } private static LoadingSheetResponse ToResponse(LoadingSheet s) => - new(s.Id, s.FK_RideId, s.FK_SourceWarehouseId, - s.SourceWarehouse?.Name ?? string.Empty, - s.Status, - s.DispatchConfirmedAt, s.DispatchConfirmedBy, - s.ReceiptConfirmedAt, s.ReceiptConfirmedBy, - s.CreatedAt, + new(s.Id, s.FK_RideId, s.Status, s.PopulatedBy, s.PopulatedAt, + s.ConfirmedAt, s.ConfirmedBy, s.CreatedAt, s.Items.Select(i => new LoadingSheetItemResponse( i.Id, i.FK_ItemId, i.Item?.Name ?? string.Empty, - i.QuantityDispatched, i.QuantityReceived, i.QuantityResolved)).ToList()); + i.FK_WarehouseId, i.Warehouse?.Name ?? string.Empty, + i.QuantityDispatched, i.FK_ShopPOItemId)).ToList(), + s.Orders.Select(o => new LoadingSheetOrderResponse(o.FK_ShopPOId)).ToList()); } diff --git a/Distribution/Features/Order/IOrderRepository.cs b/Distribution/Features/Order/IOrderRepository.cs deleted file mode 100644 index 856f12c..0000000 --- a/Distribution/Features/Order/IOrderRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Distribution.Features.Order; - -public interface IOrderRepository -{ - Task GetByIdAsync(Guid id); - Task> GetAllAsync(); - Task GetBySaleIdAsync(Guid saleId); - Task AddAsync(Models.Order entity); - void Update(Models.Order entity); - void Remove(Models.Order entity); - Task> GetItemsByOrderIdAsync(Guid orderId); - Task> GetByStoreIdAsync(Guid storeId); - Task AddItemsAsync(IEnumerable items); - Task> GetPendingByRouteIdAsync(Guid routeId); -} diff --git a/Distribution/Features/Order/OrderController.cs b/Distribution/Features/Order/OrderController.cs deleted file mode 100644 index a5f528c..0000000 --- a/Distribution/Features/Order/OrderController.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Distribution.Features.Order; - -[ApiController] -[Route("api/orders")] -public class OrderController(OrderService service) : ControllerBase -{ - [HttpGet] - public async Task GetAll() => - Ok(await service.GetAllAsync()); - - [HttpGet("{id:guid}")] - public async Task GetById(Guid id) - { - var result = await service.GetByIdAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpGet("store/{storeId:guid}")] - public async Task GetByStore(Guid storeId) - { - var result = await service.GetByStoreIdAsync(storeId); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : Ok(result); - } - - [HttpPost] - public async Task Create(CreateOrderRequest request, CancellationToken ct) - { - try - { - var result = await service.CreateAsync(request, ct); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : CreatedAtAction(nameof(GetById), new { id = result.Id }, result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPut("{id:guid}")] - public async Task Update(Guid id, UpdateOrderRequest request, CancellationToken ct) - { - try - { - var result = await service.UpdateAsync(id, request, ct); - return result is null ? NotFound() : Ok(result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpDelete("{id:guid}")] - public async Task Delete(Guid id, CancellationToken ct) - { - var deleted = await service.DeleteAsync(id, ct); - return deleted ? NoContent() : NotFound(); - } -} diff --git a/Distribution/Features/Order/OrderDTOs.cs b/Distribution/Features/Order/OrderDTOs.cs deleted file mode 100644 index 247eea4..0000000 --- a/Distribution/Features/Order/OrderDTOs.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Order; - -public record CreateOrderRequest(Guid SaleId); - -public record UpdateOrderRequest(OrderStatus Status); - -public record OrderItemResponse(Guid ItemId, int Quantity, int QuantityFulfilled, decimal UnitPrice); - -public record OrderResponse( - Guid Id, - Guid SaleId, - DateTime OrderDate, - Guid StoreId, - decimal TotalAmount, - OrderStatus Status, - DateTime? FulfilledAt, - List Items, - bool IsActive, - DateTime CreatedAt); diff --git a/Distribution/Features/Order/OrderRepository.cs b/Distribution/Features/Order/OrderRepository.cs deleted file mode 100644 index 20fe8bb..0000000 --- a/Distribution/Features/Order/OrderRepository.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Distribution.Data; -using Distribution.Models; -using Microsoft.EntityFrameworkCore; - -namespace Distribution.Features.Order; - -public class OrderRepository(AppDBContext context) : IOrderRepository -{ - public async Task GetByIdAsync(Guid id) => - await context.Orders.FindAsync(id); - - public async Task> GetAllAsync() => - await context.Orders.ToListAsync(); - - public async Task GetBySaleIdAsync(Guid saleId) => - await context.Orders.FirstOrDefaultAsync(o => o.FK_SaleId == saleId && o.IsActive); - - public async Task AddAsync(Models.Order entity) => - await context.Orders.AddAsync(entity); - - public void Update(Models.Order entity) => - context.Orders.Update(entity); - - public void Remove(Models.Order entity) - { - entity.Status = Models.OrderStatus.Cancelled; - entity.IsActive = false; - context.Orders.Update(entity); - } - - public async Task> GetItemsByOrderIdAsync(Guid orderId) => - await context.OrderItems.Where(oi => oi.FK_OrderId == orderId).ToListAsync(); - - public async Task> GetByStoreIdAsync(Guid storeId) => - await context.Orders.Where(o => o.FK_StoreId == storeId && o.IsActive).ToListAsync(); - - public async Task AddItemsAsync(IEnumerable items) => - await context.OrderItems.AddRangeAsync(items); - - public async Task> GetPendingByRouteIdAsync(Guid routeId) => - await context.Orders - .Include(o => o.Store) - .Include(o => o.OrderItems) - .ThenInclude(i => i.Item) - .Where(o => o.IsActive - && o.Store.FK_RouteId == routeId - && (o.Status == OrderStatus.Pending || o.Status == OrderStatus.PartiallyFulfilled)) - .ToListAsync(); -} diff --git a/Distribution/Features/Order/OrderService.cs b/Distribution/Features/Order/OrderService.cs deleted file mode 100644 index 9e9f8b7..0000000 --- a/Distribution/Features/Order/OrderService.cs +++ /dev/null @@ -1,158 +0,0 @@ -using Distribution.Features.Sale; -using Distribution.Features.Item; -using Distribution.Features.PriceList; -using Distribution.Features.Store; -using Distribution.Features.Stock; -using Distribution.Infra.Authorization; -using Distribution.Infra.UoW; -using Distribution.Models; - -namespace Distribution.Features.Order; - -public class OrderService( - IOrderRepository repo, - IStoreRepository storeRepo, - IItemRepository itemRepo, - IStockRepository stockRepo, - PriceListService priceListService, - ISaleRepository saleRepo, - IUnitOfWork uow, - ICurrentUserService currentUser, - IScopeAccessService scopeAccess) -{ - private const int GlobalScopeRoleLevel = 50; - - private static OrderResponse ToResponse(Models.Order o, List items) => - new(o.Id, o.FK_SaleId, o.OrderDate, o.FK_StoreId, o.TotalAmount, o.Status, o.FulfilledAt, - items.Select(i => new OrderItemResponse(i.FK_ItemId, i.Quantity, i.QuantityFulfilled, i.UnitPrice)).ToList(), - o.IsActive, o.CreatedAt); - - private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel; - - private async Task HasStoreScopeAsync(Guid storeId) - { - if (HasGlobalScope || currentUser.UserId is null) return HasGlobalScope; - return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId); - } - - public async Task> GetAllAsync() - { - // Deleted orders stay IsActive=false but remain visible with a Cancelled status — - // Delete never removes the row from the list, only marks it cancelled. - var orders = (await repo.GetAllAsync()).ToList(); - if (!HasGlobalScope && currentUser.UserId is not null) - { - var accessibleStoreIds = (await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value)).ToHashSet(); - orders = orders.Where(o => accessibleStoreIds.Contains(o.FK_StoreId)).ToList(); - } - var result = new List(); - foreach (var order in orders) - { - var items = await repo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(order, items)); - } - return result; - } - - public async Task GetByIdAsync(Guid id) - { - var order = await repo.GetByIdAsync(id); - if (order is null || !order.IsActive) return null; - if (!await HasStoreScopeAsync(order.FK_StoreId)) return null; - var items = await repo.GetItemsByOrderIdAsync(id); - return ToResponse(order, items); - } - - public async Task?> GetByStoreIdAsync(Guid storeId) - { - if (!await HasStoreScopeAsync(storeId)) return null; - var orders = await repo.GetByStoreIdAsync(storeId); - var result = new List(); - foreach (var order in orders) - { - var items = await repo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(order, items)); - } - return result; - } - - public async Task CreateAsync(CreateOrderRequest request, CancellationToken ct = default) - { - var sale = await saleRepo.GetByIdAsync(request.SaleId); - if (sale is null || !sale.IsActive) return null; - if (!await HasStoreScopeAsync(sale.FK_StoreId)) return null; - - var existingOrder = await repo.GetBySaleIdAsync(request.SaleId) - ?? throw new InvalidOperationException("Orders are created automatically from sales"); - - var items = await repo.GetItemsByOrderIdAsync(existingOrder.Id); - return ToResponse(existingOrder, items); - } - - public async Task UpdateAsync(Guid id, UpdateOrderRequest request, CancellationToken ct = default) - { - // TEMPORARY: see DeleteAsync/SaleService — store-scope enforcement depends on the broken - // auth middleware (testbug.md #28) and would reject every update. Skipped for now. - var order = await repo.GetByIdAsync(id); - if (order is null || !order.IsActive) return null; - - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId) - ?? throw new InvalidOperationException("Sale not found for this order"); - - order.Status = request.Status; - order.FulfilledAt = request.Status == OrderStatus.Fulfilled ? DateTime.Now : null; - - sale.Status = request.Status switch - { - OrderStatus.Fulfilled => SaleStatus.Completed, - OrderStatus.Cancelled => SaleStatus.Cancelled, - _ => SaleStatus.Pending - }; - sale.CompletedAt = request.Status == OrderStatus.Fulfilled ? DateTime.Now : null; - - await uow.BeginAsync(ct); - try - { - repo.Update(order); - saleRepo.Update(sale); - await uow.CommitAsync(ct); - } - catch - { - await uow.RollbackAsync(ct); - throw; - } - - var items = await repo.GetItemsByOrderIdAsync(id); - return ToResponse(order, items); - } - - public async Task DeleteAsync(Guid id, CancellationToken ct = default) - { - // TEMPORARY: see SaleService — store-scope enforcement depends on the broken auth - // middleware (testbug.md #28) and would reject every delete. Skipped for now. - var order = await repo.GetByIdAsync(id); - if (order is null || !order.IsActive) return false; - - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId); - - await uow.BeginAsync(ct); - try - { - repo.Remove(order); - if (sale is not null) - { - sale.Status = SaleStatus.Cancelled; - sale.CompletedAt = null; - saleRepo.Update(sale); - } - await uow.CommitAsync(ct); - } - catch - { - await uow.RollbackAsync(ct); - throw; - } - return true; - } -} diff --git a/Distribution/Features/Payment/FlatPaymentController.cs b/Distribution/Features/Payment/FlatPaymentController.cs deleted file mode 100644 index a927c47..0000000 --- a/Distribution/Features/Payment/FlatPaymentController.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Distribution.Features.Payment; - -[ApiController] -[Route("api/payments")] -public class FlatPaymentController(PaymentService service) : ControllerBase -{ - [HttpGet] - public async Task GetAll( - [FromQuery] Guid? storeId, - [FromQuery] Guid? saleId, - [FromQuery] int page = 1, - [FromQuery] int pageSize = 20) - { - var result = await service.GetAllAsync(storeId, saleId, page, pageSize); - return Ok(result); - } - - [HttpGet("{id:guid}")] - public async Task GetById(Guid id) - { - var result = await service.GetByIdAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpPost] - public async Task Create(CreateFlatPaymentRequest request, CancellationToken ct) - { - try - { - var inner = new CreatePaymentRequest(request.Amount, request.Method, request.CollectedByUserId); - var result = await service.CreateAsync(request.SaleId, inner, ct); - return result is null ? NotFound(new { error = "Sale not found or access denied" }) : Ok(result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } -} diff --git a/Distribution/Features/Payment/IPaymentRepository.cs b/Distribution/Features/Payment/IPaymentRepository.cs index 5e7d79d..6d26d14 100644 --- a/Distribution/Features/Payment/IPaymentRepository.cs +++ b/Distribution/Features/Payment/IPaymentRepository.cs @@ -1,12 +1,13 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.Payment; public interface IPaymentRepository { Task GetByIdAsync(Guid id); - Task> GetAllAsync(Guid? storeId, Guid? saleId, int page, int pageSize); - Task GetCountAsync(Guid? storeId, Guid? saleId); - Task> GetBySaleIdAsync(Guid saleId); + Task> GetAllAsync(Guid? invoiceId, int page, int pageSize); + Task GetCountAsync(Guid? invoiceId); + Task> GetByInvoiceIdAsync(Guid invoiceId); Task AddAsync(Models.Payment payment); + void Update(Models.Payment payment); } diff --git a/Distribution/Features/Payment/PaymentController.cs b/Distribution/Features/Payment/PaymentController.cs index 18fe7f3..d3e6e91 100644 --- a/Distribution/Features/Payment/PaymentController.cs +++ b/Distribution/Features/Payment/PaymentController.cs @@ -3,22 +3,22 @@ namespace Distribution.Features.Payment; [ApiController] -[Route("api/sales/{saleId:guid}/payments")] +[Route("api/invoices/{invoiceId:guid}/payments")] public class PaymentController(PaymentService service) : ControllerBase { [HttpGet] - public async Task GetBySale(Guid saleId) + public async Task GetByInvoice(Guid invoiceId) { - var result = await service.GetBySaleIdAsync(saleId); + var result = await service.GetByInvoiceIdAsync(invoiceId); return result is null ? NotFound() : Ok(result); } [HttpPost] - public async Task Create(Guid saleId, CreatePaymentRequest request, CancellationToken ct) + public async Task Create(Guid invoiceId, CreatePaymentRequest request, CancellationToken ct) { try { - var result = await service.CreateAsync(saleId, request, ct); + var result = await service.CreateAsync(invoiceId, request, ct); return result is null ? NotFound() : Ok(result); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } diff --git a/Distribution/Features/Payment/PaymentDTOs.cs b/Distribution/Features/Payment/PaymentDTOs.cs index 83e978a..1a9eb55 100644 --- a/Distribution/Features/Payment/PaymentDTOs.cs +++ b/Distribution/Features/Payment/PaymentDTOs.cs @@ -1,25 +1,24 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.Payment; public record CreatePaymentRequest( decimal Amount, PaymentMethod Method, - // TEMPORARY: auth middleware doesn't resolve a logged-in user yet — see testbug.md #28. - Guid? CollectedByUserId = null); - -public record CreateFlatPaymentRequest( - Guid SaleId, - decimal Amount, - PaymentMethod Method, + EntryMode EntryMode = EntryMode.RealTime, + string? ChequeNumber = null, + DateTime? ChequeDate = null, Guid? CollectedByUserId = null); public record PaymentResponse( Guid Id, - Guid SaleId, - Guid StoreId, + Guid InvoiceId, decimal Amount, PaymentMethod Method, + EntryMode EntryMode, + string? ChequeNumber, + DateTime? ChequeDate, DateTime CollectedAt, Guid CollectedBy, + Guid? RecordedBy, DateTime CreatedAt); diff --git a/Distribution/Features/Payment/PaymentRepository.cs b/Distribution/Features/Payment/PaymentRepository.cs index 13cd944..b490bf7 100644 --- a/Distribution/Features/Payment/PaymentRepository.cs +++ b/Distribution/Features/Payment/PaymentRepository.cs @@ -1,4 +1,4 @@ -using Distribution.Data; +using Distribution.Data; using Distribution.Models; using Microsoft.EntityFrameworkCore; @@ -9,29 +9,27 @@ public class PaymentRepository(AppDBContext context) : IPaymentRepository public async Task GetByIdAsync(Guid id) => await context.Payments.FirstOrDefaultAsync(p => p.Id == id && p.IsActive); - public async Task> GetAllAsync(Guid? storeId, Guid? saleId, int page, int pageSize) => + public async Task> GetAllAsync(Guid? invoiceId, int page, int pageSize) => await context.Payments - .Where(p => p.IsActive - && (storeId == null || p.FK_StoreId == storeId) - && (saleId == null || p.FK_SaleId == saleId)) + .Where(p => p.IsActive && (invoiceId == null || p.FK_InvoiceId == invoiceId)) .OrderByDescending(p => p.CollectedAt) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); - public async Task GetCountAsync(Guid? storeId, Guid? saleId) => + public async Task GetCountAsync(Guid? invoiceId) => await context.Payments - .Where(p => p.IsActive - && (storeId == null || p.FK_StoreId == storeId) - && (saleId == null || p.FK_SaleId == saleId)) - .CountAsync(); + .CountAsync(p => p.IsActive && (invoiceId == null || p.FK_InvoiceId == invoiceId)); - public async Task> GetBySaleIdAsync(Guid saleId) => + public async Task> GetByInvoiceIdAsync(Guid invoiceId) => await context.Payments - .Where(p => p.FK_SaleId == saleId && p.IsActive) + .Where(p => p.FK_InvoiceId == invoiceId && p.IsActive) .OrderBy(p => p.CollectedAt) .ToListAsync(); public async Task AddAsync(Models.Payment payment) => await context.Payments.AddAsync(payment); + + public void Update(Models.Payment payment) => + context.Payments.Update(payment); } diff --git a/Distribution/Features/Payment/PaymentService.cs b/Distribution/Features/Payment/PaymentService.cs index e98cdc1..f20e7b0 100644 --- a/Distribution/Features/Payment/PaymentService.cs +++ b/Distribution/Features/Payment/PaymentService.cs @@ -1,5 +1,4 @@ -using Distribution.Features.Sale; -using Distribution.Features.Stock; +using Distribution.Features.Invoice; using Distribution.Infra.Authorization; using Distribution.Infra.UoW; using Distribution.Models; @@ -8,55 +7,52 @@ namespace Distribution.Features.Payment; public class PaymentService( IPaymentRepository repo, - ISaleRepository saleRepo, + IInvoiceRepository invoiceRepo, IUnitOfWork uow, ICurrentUserService currentUser) { private static PaymentResponse ToResponse(Models.Payment p) => - new(p.Id, p.FK_SaleId, p.FK_StoreId, p.Amount, p.Method, p.CollectedAt, p.CollectedBy, p.CreatedAt); + new(p.Id, p.FK_InvoiceId, p.Amount, p.Method, p.EntryMode, p.ChequeNumber, p.ChequeDate, + p.CollectedAt, p.CollectedBy, p.RecordedBy, p.CreatedAt); - public async Task> GetAllAsync(Guid? storeId, Guid? saleId, int page, int pageSize) + public async Task?> GetByInvoiceIdAsync(Guid invoiceId) { - var total = await repo.GetCountAsync(storeId, saleId); - var items = await repo.GetAllAsync(storeId, saleId, page, pageSize); - return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); - } + var invoice = await invoiceRepo.GetByIdAsync(invoiceId); + if (invoice is null || !invoice.IsActive) return null; - public async Task GetByIdAsync(Guid id) - { - var payment = await repo.GetByIdAsync(id); - return payment is null ? null : ToResponse(payment); - } - - public async Task?> GetBySaleIdAsync(Guid saleId) - { - var sale = await saleRepo.GetByIdAsync(saleId); - if (sale is null || !sale.IsActive) return null; - - var payments = await repo.GetBySaleIdAsync(saleId); + var payments = await repo.GetByInvoiceIdAsync(invoiceId); return payments.Select(ToResponse).ToList(); } - public async Task CreateAsync(Guid saleId, CreatePaymentRequest request, CancellationToken ct = default) + public async Task CreateAsync(Guid invoiceId, CreatePaymentRequest request, CancellationToken ct = default) { - var sale = await saleRepo.GetByIdAsync(saleId); - if (sale is null || !sale.IsActive) return null; - if (sale.Status == SaleStatus.Cancelled) - throw new InvalidOperationException("Cannot record a payment against a cancelled sale"); + var invoice = await invoiceRepo.GetByIdAsync(invoiceId); + if (invoice is null || !invoice.IsActive) return null; + if (invoice.Status == InvoiceStatus.Finalized) + throw new InvalidOperationException("Cannot record a payment against a finalized invoice"); - // TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware - // (testbug.md #28) — fall back to the explicitly supplied user until that's fixed. - var userId = currentUser.UserId ?? request.CollectedByUserId + if (request.Method == PaymentMethod.Cheque && + (string.IsNullOrWhiteSpace(request.ChequeNumber) || request.ChequeDate is null)) + throw new InvalidOperationException("ChequeNumber and ChequeDate are required when Method is Cheque"); + + var recorderId = currentUser.UserId ?? request.CollectedByUserId ?? throw new InvalidOperationException("CollectedByUserId is required while auth is unavailable"); + var collectedBy = request.CollectedByUserId ?? recorderId; + var recordedBy = request.EntryMode == EntryMode.DayEndManual && collectedBy != recorderId + ? recorderId + : (Guid?)null; var payment = new Models.Payment { - FK_SaleId = saleId, - FK_StoreId = sale.FK_StoreId, + FK_InvoiceId = invoiceId, Amount = request.Amount, Method = request.Method, + EntryMode = request.EntryMode, + ChequeNumber = request.Method == PaymentMethod.Cheque ? request.ChequeNumber : null, + ChequeDate = request.Method == PaymentMethod.Cheque ? request.ChequeDate : null, CollectedAt = DateTime.Now, - CollectedBy = userId + CollectedBy = collectedBy, + RecordedBy = recordedBy }; await uow.BeginAsync(ct); @@ -64,17 +60,16 @@ public class PaymentService( { await repo.AddAsync(payment); - var allPayments = await repo.GetBySaleIdAsync(saleId); + var allPayments = await repo.GetByInvoiceIdAsync(invoiceId); var total = allPayments.Sum(p => p.Amount) + request.Amount; - sale.PaymentStatus = total == 0 + invoice.PaymentStatus = total == 0 ? PaymentStatus.Pending - : total < sale.TotalAmount + : total < invoice.TotalAmount ? PaymentStatus.PartiallyPaid : PaymentStatus.Paid; - saleRepo.Update(sale); - + invoiceRepo.Update(invoice); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } diff --git a/Distribution/Features/Region/IRegionRepository.cs b/Distribution/Features/Region/IRegionRepository.cs index de27c38..36b8c95 100644 --- a/Distribution/Features/Region/IRegionRepository.cs +++ b/Distribution/Features/Region/IRegionRepository.cs @@ -42,5 +42,5 @@ public interface IRegionRepository Task> GetRoutesAsync(Guid regionId); Task> GetStoresByRouteIdsAsync(List routeIds); - Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive); + Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive); } diff --git a/Distribution/Features/Region/RegionRepository.cs b/Distribution/Features/Region/RegionRepository.cs index 428ad5e..c760c31 100644 --- a/Distribution/Features/Region/RegionRepository.cs +++ b/Distribution/Features/Region/RegionRepository.cs @@ -129,11 +129,11 @@ public class RegionRepository(AppDBContext context) : IRegionRepository public async Task> GetStoresByRouteIdsAsync(List routeIds) => await context.Stores.Where(s => routeIds.Contains(s.FK_RouteId) && s.IsActive).ToListAsync(); - public async Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive) => - await (from o in context.Orders + public async Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive) => + await (from o in context.ShopPOs join s in context.Stores on o.FK_StoreId equals s.Id join r in context.Routes on s.FK_RouteId equals r.Id where r.FK_RegionId == regionId && o.IsActive && s.IsActive && r.IsActive - && o.OrderDate >= periodStart && o.OrderDate < periodEndExclusive + && o.CreatedAt >= periodStart && o.CreatedAt < periodEndExclusive select o).ToListAsync(); } diff --git a/Distribution/Features/Region/RegionService.cs b/Distribution/Features/Region/RegionService.cs index e04cc2d..ce26dc8 100644 --- a/Distribution/Features/Region/RegionService.cs +++ b/Distribution/Features/Region/RegionService.cs @@ -219,7 +219,7 @@ public class RegionService(IRegionRepository repo, IUnitOfWork uow, ICurrentUser budget?.BudgetAmount, orders.Count, orders.Sum(o => o.TotalAmount), - orders.Count == 0 ? null : orders.Max(o => o.OrderDate), + orders.Count == 0 ? null : orders.Max(o => o.CreatedAt), taxRule?.RuleConfig, agencyMaps.Select(m => m.FK_AgencyUserId).ToList()); } diff --git a/Distribution/Features/Returns/IReturnRepository.cs b/Distribution/Features/Returns/IReturnRepository.cs index efd2bce..3dc7545 100644 --- a/Distribution/Features/Returns/IReturnRepository.cs +++ b/Distribution/Features/Returns/IReturnRepository.cs @@ -4,11 +4,11 @@ public interface IReturnRepository { Task GetByIdAsync(Guid id); Task> GetAllAsync(); - Task> GetByOrderIdAsync(Guid orderId); + Task> GetByShopPOIdAsync(Guid shopPOId); Task AddAsync(Models.SaleReturn entity); void Update(Models.SaleReturn entity); Task AddCreditNoteAsync(Models.CreditNote entity); - /// Whether this store has ever had this item on any of its (active) orders. + /// Whether this store has ever had this item on any of its (active) ShopPOs. Task StoreHasPriorSaleAsync(Guid storeId, Guid itemId); } diff --git a/Distribution/Features/Returns/ReturnController.cs b/Distribution/Features/Returns/ReturnController.cs index 4612ed5..24cfb7c 100644 --- a/Distribution/Features/Returns/ReturnController.cs +++ b/Distribution/Features/Returns/ReturnController.cs @@ -1,4 +1,4 @@ -using Distribution.Infra.Authorization; +using Distribution.Infra.Authorization; using Microsoft.AspNetCore.Mvc; namespace Distribution.Features.Returns; @@ -28,15 +28,13 @@ public class ReturnController(ReturnService service, ICurrentUserService current catch (InvalidOperationException ex) { return Conflict(new { error = ex.Message }); } } - [HttpGet("api/orders/{id:guid}/returns")] - public async Task GetByOrder(Guid id) => - Ok(await service.GetByOrderIdAsync(id)); + [HttpGet("api/shop-pos/{id:guid}/returns")] + public async Task GetByShopPO(Guid id) => + Ok(await service.GetByShopPOIdAsync(id)); - [HttpPost("api/orders/{id:guid}/returns")] + [HttpPost("api/shop-pos/{id:guid}/returns")] public async Task Create(Guid id, CreateSaleReturnRequest request, CancellationToken ct) { - // TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware - // (testbug.md #28) — fall back to the explicitly supplied user until that's fixed. var userId = currentUser.UserId ?? request.CreatedByUserId; if (userId is null) return BadRequest(new { error = "CreatedByUserId is required while auth is unavailable" }); try @@ -44,6 +42,7 @@ public class ReturnController(ReturnService service, ICurrentUserService current var result = await service.CreateAsync(id, request, userId.Value, ct); return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); } + catch (NotImplementedException ex) { return StatusCode(501, new { error = ex.Message }); } catch (InvalidOperationException ex) { return Conflict(new { error = ex.Message }); } } } diff --git a/Distribution/Features/Returns/ReturnDTOs.cs b/Distribution/Features/Returns/ReturnDTOs.cs index 834ca98..ead721d 100644 --- a/Distribution/Features/Returns/ReturnDTOs.cs +++ b/Distribution/Features/Returns/ReturnDTOs.cs @@ -27,7 +27,7 @@ public record SaleReturnItemResponse( public record SaleReturnResponse( Guid Id, - Guid OrderId, + Guid ShopPOId, ReturnMode Mode, decimal TotalCreditAmount, decimal OrderTotalAmountAfter, diff --git a/Distribution/Features/Returns/ReturnRepository.cs b/Distribution/Features/Returns/ReturnRepository.cs index ee553f5..497f8ae 100644 --- a/Distribution/Features/Returns/ReturnRepository.cs +++ b/Distribution/Features/Returns/ReturnRepository.cs @@ -7,23 +7,23 @@ public class ReturnRepository(AppDBContext context) : IReturnRepository { public async Task GetByIdAsync(Guid id) => await context.SaleReturns - .Include(r => r.Order) + .Include(r => r.ShopPO) .Include(r => r.Items).ThenInclude(i => i.Item) .FirstOrDefaultAsync(r => r.Id == id); public async Task> GetAllAsync() => await context.SaleReturns - .Include(r => r.Order) + .Include(r => r.ShopPO) .Include(r => r.Items).ThenInclude(i => i.Item) .Where(r => r.IsActive) .OrderByDescending(r => r.CreatedAt) .ToListAsync(); - public async Task> GetByOrderIdAsync(Guid orderId) => + public async Task> GetByShopPOIdAsync(Guid shopPOId) => await context.SaleReturns - .Include(r => r.Order) + .Include(r => r.ShopPO) .Include(r => r.Items).ThenInclude(i => i.Item) - .Where(r => r.FK_OrderId == orderId && r.IsActive) + .Where(r => r.FK_ShopPOId == shopPOId && r.IsActive) .OrderByDescending(r => r.CreatedAt) .ToListAsync(); @@ -37,7 +37,7 @@ public class ReturnRepository(AppDBContext context) : IReturnRepository await context.CreditNotes.AddAsync(entity); public async Task StoreHasPriorSaleAsync(Guid storeId, Guid itemId) => - await context.OrderItems - .Include(oi => oi.Order) - .AnyAsync(oi => oi.Order.FK_StoreId == storeId && oi.Order.IsActive && oi.FK_ItemId == itemId); + await context.ShopPOItems + .Include(oi => oi.ShopPO) + .AnyAsync(oi => oi.ShopPO.FK_StoreId == storeId && oi.ShopPO.IsActive && oi.FK_ItemId == itemId); } diff --git a/Distribution/Features/Returns/ReturnService.cs b/Distribution/Features/Returns/ReturnService.cs index 731bc18..83ab2e5 100644 --- a/Distribution/Features/Returns/ReturnService.cs +++ b/Distribution/Features/Returns/ReturnService.cs @@ -1,7 +1,5 @@ using Distribution.Features.Item; -using Distribution.Features.Order; -using Distribution.Features.Ride; -using Distribution.Features.Sale; +using Distribution.Features.ShopPO; using Distribution.Features.Stock; using Distribution.Infra.UoW; using Distribution.Models; @@ -10,9 +8,7 @@ namespace Distribution.Features.Returns; public class ReturnService( IReturnRepository repo, - IOrderRepository orderRepo, - ISaleRepository saleRepo, - IRideRepository rideRepo, + IShopPORepository shopPORepo, IItemRepository itemRepo, IStockRepository stockRepo, IUnitOfWork uow) @@ -21,7 +17,7 @@ public class ReturnService( new(i.Id, i.FK_ItemId, i.Item.Sku, i.Item.Name, i.Quantity, i.ReasonCode, i.UnitPrice); private static SaleReturnResponse Map(SaleReturn r) => - new(r.Id, r.FK_OrderId, r.Mode, r.TotalCreditAmount, r.Order.TotalAmount, r.IsActive, r.CreatedAt, + new(r.Id, r.FK_ShopPOId, r.Mode, r.TotalCreditAmount, r.ShopPO.TotalAmount, r.IsActive, r.CreatedAt, r.Items.Where(i => i.IsActive).Select(MapItem).ToList()); public async Task GetByIdAsync(Guid id) @@ -58,141 +54,9 @@ public class ReturnService( return Map(r); } - public async Task> GetByOrderIdAsync(Guid orderId) => - (await repo.GetByOrderIdAsync(orderId)).Select(Map).ToList(); + public async Task> GetByShopPOIdAsync(Guid shopPOId) => + (await repo.GetByShopPOIdAsync(shopPOId)).Select(Map).ToList(); - /// - /// Records a return recognized during the same store visit as an open order and settles it - /// immediately: stock is credited back to the rep's vehicle, and either the order total is - /// reduced (CreditDeduction) or the matching order line quantities are reduced (ItemExchange). - /// A return is only allowed for an item the store has previously ordered. - /// - public async Task CreateAsync(Guid orderId, CreateSaleReturnRequest request, Guid createdByUserId, CancellationToken ct = default) - { - var order = await orderRepo.GetByIdAsync(orderId); - if (order is null || !order.IsActive) - throw new InvalidOperationException("Order not found."); - if (order.Status is OrderStatus.Cancelled or OrderStatus.Fulfilled) - throw new InvalidOperationException("Cannot record a return against a closed order."); - - if (request.Items is null || request.Items.Count == 0) - throw new InvalidOperationException("A return must have at least one line item."); - - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId) - ?? throw new InvalidOperationException("Sale not found for this order."); - if (sale.FK_RideId is null) - throw new InvalidOperationException("A return can only be recorded for an order created during an active ride."); - - var ride = await rideRepo.GetByIdAsync(sale.FK_RideId.Value) - ?? throw new InvalidOperationException("Ride not found."); - var vehicleId = ride.FK_VehicleId; - - var orderItems = await orderRepo.GetItemsByOrderIdAsync(orderId); - var orderItemsByItemId = orderItems.ToDictionary(oi => oi.FK_ItemId); - - var saleReturn = new SaleReturn - { - FK_OrderId = orderId, - Mode = request.Mode, - CreatedByUserId = createdByUserId - }; - - foreach (var line in request.Items) - { - if (line.Quantity <= 0) - throw new InvalidOperationException("Return quantity must be greater than zero."); - - var item = await itemRepo.GetByIdAsync(line.ItemId) - ?? throw new InvalidOperationException($"Item {line.ItemId} not found."); - - if (!await repo.StoreHasPriorSaleAsync(order.FK_StoreId, line.ItemId)) - throw new InvalidOperationException($"No prior sale of item '{item.Name}' found for this store."); - - var unitPrice = orderItemsByItemId.TryGetValue(line.ItemId, out var matchingOrderItem) - ? matchingOrderItem.UnitPrice - : item.SalePrice ?? 0; - - saleReturn.Items.Add(new SaleReturnItem - { - FK_ItemId = line.ItemId, - Quantity = line.Quantity, - ReasonCode = line.ReasonCode, - UnitPrice = unitPrice - }); - } - - await uow.BeginAsync(ct); - try - { - foreach (var line in saleReturn.Items) - { - var balance = await stockRepo.GetBalanceAsync(line.FK_ItemId, vehicleId); - if (balance is null) - { - await stockRepo.AddBalanceAsync(new StockBalance - { - FK_ItemId = line.FK_ItemId, - LocationId = vehicleId, - LocationType = LocationType.Vehicle, - Quantity = line.Quantity - }); - } - else - { - balance.Quantity += line.Quantity; - balance.UpdatedAt = DateTime.Now; - stockRepo.UpdateBalance(balance); - } - - await stockRepo.AddMovementAsync(new StockMovement - { - FK_ItemId = line.FK_ItemId, - FromLocationId = StockService.ExternalLocationId, - FromLocationType = LocationType.External, - ToLocationId = vehicleId, - ToLocationType = LocationType.Vehicle, - Quantity = line.Quantity, - Type = MovementType.CustomerReturn, - ReasonCode = line.ReasonCode.ToString(), - ReferenceId = saleReturn.Id, - CreatedBy = createdByUserId - }); - } - - await repo.AddAsync(saleReturn); - - if (request.Mode == ReturnMode.CreditDeduction) - { - var total = saleReturn.Items.Sum(i => i.Quantity * i.UnitPrice); - saleReturn.TotalCreditAmount = total; - order.TotalAmount = Math.Max(0, order.TotalAmount - total); - orderRepo.Update(order); - - await repo.AddCreditNoteAsync(new CreditNote - { - FK_SaleReturnId = saleReturn.Id, - Amount = total - }); - } - else // ItemExchange - { - foreach (var line in saleReturn.Items) - { - if (!orderItemsByItemId.TryGetValue(line.FK_ItemId, out var orderItem)) - continue; // no matching line on this order — nothing to offset - - var offsetQty = Math.Min(line.Quantity, orderItem.Quantity); - orderItem.Quantity -= (int)offsetQty; - order.TotalAmount = Math.Max(0, order.TotalAmount - offsetQty * orderItem.UnitPrice); - } - orderRepo.Update(order); - } - - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - var saved = await repo.GetByIdAsync(saleReturn.Id); - return Map(saved!); - } + public Task CreateAsync(Guid shopPOId, CreateSaleReturnRequest request, Guid createdByUserId, CancellationToken ct = default) => + throw new NotImplementedException("Return flow is being redesigned — not yet implemented."); } diff --git a/Distribution/Features/Ride/IRideCancelRequestRepository.cs b/Distribution/Features/Ride/IRideCancelRequestRepository.cs deleted file mode 100644 index bcd140b..0000000 --- a/Distribution/Features/Ride/IRideCancelRequestRepository.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Ride; - -public interface IRideCancelRequestRepository -{ - Task GetByIdAsync(Guid id); - Task GetByRideIdAsync(Guid rideId); - Task GetPendingByRideIdAsync(Guid rideId); - Task> GetAllAsync(CancelRequestStatus? status, int page, int pageSize); - Task GetCountAsync(CancelRequestStatus? status); - Task AddAsync(RideCancelRequest request); - void Update(RideCancelRequest request); -} diff --git a/Distribution/Features/Ride/IRideRepository.cs b/Distribution/Features/Ride/IRideRepository.cs index 8a44d30..bc6206c 100644 --- a/Distribution/Features/Ride/IRideRepository.cs +++ b/Distribution/Features/Ride/IRideRepository.cs @@ -1,22 +1,13 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.Ride; public interface IRideRepository { Task GetByIdAsync(Guid id); - Task> GetAllAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize); - Task GetCountAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId); - Task HasOpenOrActiveRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null); - Task> GetActiveRidesAsync(Guid? excludeRideId = null); - Task> GetActiveOrdersByRouteIdAsync(Guid routeId); + Task> GetAllAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize); + Task GetCountAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId); + Task HasOpenRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null); Task AddAsync(DeliveryRun ride); void Update(DeliveryRun ride); } - -public record OrderSummaryModel( - Guid Id, - Guid StoreId, - string StoreName, - DateTime OrderDate, - decimal TotalAmount); diff --git a/Distribution/Features/Ride/RideCancelRequestRepository.cs b/Distribution/Features/Ride/RideCancelRequestRepository.cs deleted file mode 100644 index c9bf85e..0000000 --- a/Distribution/Features/Ride/RideCancelRequestRepository.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Distribution.Data; -using Distribution.Models; -using Microsoft.EntityFrameworkCore; - -namespace Distribution.Features.Ride; - -public class RideCancelRequestRepository(AppDBContext context) : IRideCancelRequestRepository -{ - public async Task GetByIdAsync(Guid id) => - await context.RideCancelRequests.FirstOrDefaultAsync(r => r.Id == id); - - public async Task GetByRideIdAsync(Guid rideId) => - await context.RideCancelRequests - .Where(r => r.FK_RideId == rideId) - .OrderByDescending(r => r.RequestedAt) - .FirstOrDefaultAsync(); - - public async Task GetPendingByRideIdAsync(Guid rideId) => - await context.RideCancelRequests - .FirstOrDefaultAsync(r => r.FK_RideId == rideId && r.Status == CancelRequestStatus.Pending); - - public async Task> GetAllAsync(CancelRequestStatus? status, int page, int pageSize) => - await context.RideCancelRequests - .Where(r => status == null || r.Status == status) - .OrderByDescending(r => r.RequestedAt) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(); - - public async Task GetCountAsync(CancelRequestStatus? status) => - await context.RideCancelRequests - .CountAsync(r => status == null || r.Status == status); - - public async Task AddAsync(RideCancelRequest request) => - await context.RideCancelRequests.AddAsync(request); - - public void Update(RideCancelRequest request) => - context.RideCancelRequests.Update(request); -} diff --git a/Distribution/Features/Ride/RideController.cs b/Distribution/Features/Ride/RideController.cs index 008d8ee..ec0086d 100644 --- a/Distribution/Features/Ride/RideController.cs +++ b/Distribution/Features/Ride/RideController.cs @@ -1,23 +1,21 @@ -using Distribution.Infra.Authorization; -using Distribution.Models; +using Distribution.Models; using Microsoft.AspNetCore.Mvc; namespace Distribution.Features.Ride; [ApiController] [Route("api/rides")] -public class RideController(RideService service, ICurrentUserService currentUser) : ControllerBase +public class RideController(RideService service) : ControllerBase { [HttpGet] public async Task GetAll( [FromQuery] RideStatus? status, - [FromQuery] RideType? type, [FromQuery] Guid? driverProfileId, [FromQuery] Guid? vehicleId, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { - var result = await service.GetAllAsync(status, type, driverProfileId, vehicleId, page, pageSize); + var result = await service.GetAllAsync(status, driverProfileId, vehicleId, page, pageSize); return Ok(result); } @@ -31,8 +29,12 @@ public class RideController(RideService service, ICurrentUserService currentUser [HttpPost] public async Task Create(CreateRideRequest request, CancellationToken ct) { - var result = await service.CreateAsync(request, ct); - return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); + try + { + var result = await service.CreateAsync(request, ct); + return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); + } + catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } [HttpPut("{id:guid}/driver")] @@ -47,32 +49,6 @@ public class RideController(RideService service, ICurrentUserService currentUser catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - [HttpPost("{id:guid}/open")] - public async Task Open(Guid id, CancellationToken ct) - { - try - { - var result = await service.OpenAsync(id, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/activate")] - [HttpPost("{id:guid}/activate")] - public async Task Activate(Guid id, ActivateRideRequest request, CancellationToken ct) - { - try - { - var result = await service.ActivateAsync(id, request, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/close")] [HttpPost("{id:guid}/close")] public async Task Close(Guid id, CloseRideRequest request, CancellationToken ct) { @@ -85,70 +61,15 @@ public class RideController(RideService service, ICurrentUserService currentUser catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - [HttpPost("{id:guid}/cancel-request")] - public async Task RaiseCancelRequest(Guid id, RaiseCancelRequest request, CancellationToken ct) + [HttpPost("{id:guid}/cancel")] + public async Task Cancel(Guid id, CancelRideRequest request, CancellationToken ct) { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); try { - var result = await service.RaiseCancelRequestAsync(id, request, userId, ct); + var result = await service.CancelAsync(id, request, ct); return Ok(result); } catch (KeyNotFoundException) { return NotFound(); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - - [HttpGet("cancel-requests")] - public async Task GetCancelRequests( - [FromQuery] CancelRequestStatus? status, - [FromQuery] int page = 1, - [FromQuery] int pageSize = 20) - { - var result = await service.GetCancelRequestsAsync(status, page, pageSize); - return Ok(result); - } - - [HttpPost("cancel-requests/{id:guid}/approve")] - public async Task ApproveCancelRequest(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ApproveCancelAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPost("cancel-requests/{id:guid}/reject")] - public async Task RejectCancelRequest(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.RejectCancelAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpGet("{id:guid}/cancel-request")] - public async Task GetCancelRequest(Guid id) - { - var result = await service.GetCancelRequestAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpGet("breakdown-assist/{rideId:guid}")] - public async Task GetBreakdownAssist(Guid rideId) - { - try - { - var result = await service.GetBreakdownAssistAsync(rideId); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - } } diff --git a/Distribution/Features/Ride/RideDTOs.cs b/Distribution/Features/Ride/RideDTOs.cs index d43b3c3..49beed7 100644 --- a/Distribution/Features/Ride/RideDTOs.cs +++ b/Distribution/Features/Ride/RideDTOs.cs @@ -1,73 +1,27 @@ -using Distribution.Models; -using Distribution.Features.Stock; +using Distribution.Models; namespace Distribution.Features.Ride; -// Ride (DeliveryRun) public record RideResponse( Guid Id, - RideType RideType, RideStatus Status, Guid VehicleId, string VehicleNumberPlate, Guid DriverProfileId, string DriverFullName, - Guid RouteId, - string RouteName, - Guid SourceWarehouseId, - string SourceWarehouseName, int Meterstart, int Meterend, DateTime? StartedAt, - DateTime? ActivatedAt, DateTime? ClosedAt, DateTime CreatedAt); public record CreateRideRequest( - RideType RideType, Guid VehicleId, Guid DriverProfileId, - Guid RouteId, - Guid? SourceWarehouseId); + int Meterstart); public record AssignRideDriverRequest(Guid DriverProfileId); -public record ActivateRideRequest(int Meterstart); - public record CloseRideRequest(int Meterend); -public record RaiseCancelRequest(CancelRequestType TypeCode, string Reason); - -// Cancel Request -public record RideCancelRequestResponse( - Guid Id, - Guid RideId, - CancelRequestType TypeCode, - string Reason, - Guid RequestedBy, - DateTime RequestedAt, - CancelRequestStatus Status, - Guid? ApprovedBy, - DateTime? ApprovedAt); - -public record BreakdownAssistRideResponse( - Guid RideId, - Guid VehicleId, - string VehicleNumberPlate, - Guid DriverProfileId, - string DriverFullName, - Guid RouteId, - string RouteName, - List StockLevels); - -public record BreakdownAssistOrderResponse( - Guid OrderId, - Guid StoreId, - string StoreName, - DateTime OrderDate, - decimal TotalAmount); - -public record BreakdownAssistResponse( - Guid RideId, - List ActiveRides, - List OpenOrders); +public record CancelRideRequest(CancelRequestType TypeCode, string Reason); diff --git a/Distribution/Features/Ride/RideRepository.cs b/Distribution/Features/Ride/RideRepository.cs index d2b0d07..6c52907 100644 --- a/Distribution/Features/Ride/RideRepository.cs +++ b/Distribution/Features/Ride/RideRepository.cs @@ -1,4 +1,4 @@ -using Distribution.Data; +using Distribution.Data; using Distribution.Models; using Microsoft.EntityFrameworkCore; @@ -10,59 +10,32 @@ public class RideRepository(AppDBContext context) : IRideRepository await context.DeliveryRuns .Include(r => r.Vehicle) .Include(r => r.DriverProfile).ThenInclude(dp => dp.User) - .Include(r => r.Route) - .Include(r => r.SourceWarehouse) .FirstOrDefaultAsync(r => r.Id == id); - public async Task> GetAllAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize) => + public async Task> GetAllAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize) => await context.DeliveryRuns .Include(r => r.Vehicle) .Include(r => r.DriverProfile).ThenInclude(dp => dp.User) - .Include(r => r.Route) - .Include(r => r.SourceWarehouse) .Where(r => (status == null || r.Status == status) && - (type == null || r.RideType == type) && (driverProfileId == null || r.FK_DriverProfileId == driverProfileId) && (vehicleId == null || r.FK_VehicleId == vehicleId)) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); - public async Task GetCountAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId) => + public async Task GetCountAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId) => await context.DeliveryRuns .CountAsync(r => (status == null || r.Status == status) && - (type == null || r.RideType == type) && (driverProfileId == null || r.FK_DriverProfileId == driverProfileId) && (vehicleId == null || r.FK_VehicleId == vehicleId)); - public async Task HasOpenOrActiveRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null) => + public async Task HasOpenRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null) => await context.DeliveryRuns.AnyAsync(r => r.FK_VehicleId == vehicleId && r.Id != excludeRideId && - (r.Status == RideStatus.Open || r.Status == RideStatus.Active)); - - public async Task> GetActiveRidesAsync(Guid? excludeRideId = null) => - await context.DeliveryRuns - .Include(r => r.Vehicle) - .Include(r => r.DriverProfile).ThenInclude(dp => dp.User) - .Include(r => r.Route) - .Where(r => r.Id != excludeRideId && r.Status == RideStatus.Active) - .ToListAsync(); - - public async Task> GetActiveOrdersByRouteIdAsync(Guid routeId) => - await context.Orders - .Include(o => o.Store) - .Where(o => o.IsActive && o.Store.FK_RouteId == routeId) - .OrderByDescending(o => o.OrderDate) - .Select(o => new OrderSummaryModel( - o.Id, - o.FK_StoreId, - o.Store.StoreName, - o.OrderDate, - o.TotalAmount)) - .ToListAsync(); + r.Status == RideStatus.Open); public async Task AddAsync(DeliveryRun ride) => await context.DeliveryRuns.AddAsync(ride); diff --git a/Distribution/Features/Ride/RideService.cs b/Distribution/Features/Ride/RideService.cs index 4d872a0..d4a0037 100644 --- a/Distribution/Features/Ride/RideService.cs +++ b/Distribution/Features/Ride/RideService.cs @@ -1,4 +1,4 @@ -using Distribution.Features.Stock; +using Distribution.Features.Stock; using Distribution.Features.DriverComplianceConfig; using Distribution.Features.DriverProfile; using Distribution.Infra.UoW; @@ -10,21 +10,13 @@ public class RideService( IRideRepository rideRepo, IDriverProfileRepository driverRepo, IDriverComplianceConfigRepository complianceRepo, - IRideCancelRequestRepository cancelRepo, - Features.Vehicle.IVehicleRepository vehicleRepo, IStockRepository stockRepo, IUnitOfWork uow) { - public async Task> GetAllAsync( - RideStatus? status, - RideType? type, - Guid? driverProfileId, - Guid? vehicleId, - int page, - int pageSize) + public async Task> GetAllAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize) { - var total = await rideRepo.GetCountAsync(status, type, driverProfileId, vehicleId); - var items = await rideRepo.GetAllAsync(status, type, driverProfileId, vehicleId, page, pageSize); + var total = await rideRepo.GetCountAsync(status, driverProfileId, vehicleId); + var items = await rideRepo.GetAllAsync(status, driverProfileId, vehicleId, page, pageSize); return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); } @@ -36,21 +28,18 @@ public class RideService( public async Task CreateAsync(CreateRideRequest request, CancellationToken ct = default) { - var vehicle = await vehicleRepo.GetByIdAsync(request.VehicleId) - ?? throw new InvalidOperationException("Vehicle not found"); + if (await rideRepo.HasOpenRideForVehicleAsync(request.VehicleId)) + throw new InvalidOperationException("Vehicle already has an open ride"); - var sourceWarehouseId = vehicle.DefaultWarehouseId ?? request.SourceWarehouseId; - if (!sourceWarehouseId.HasValue) - throw new InvalidOperationException("Source warehouse is required for this vehicle"); + await CheckDriverComplianceAsync(request.DriverProfileId); var ride = new DeliveryRun { - RideType = request.RideType, FK_VehicleId = request.VehicleId, FK_DriverProfileId = request.DriverProfileId, - FK_RouteId = request.RouteId, - FK_SourceWarehouseId = sourceWarehouseId.Value, - Status = RideStatus.Draft + Status = RideStatus.Open, + Meterstart = request.Meterstart, + StartedAt = DateTime.Now }; await uow.BeginAsync(ct); @@ -59,46 +48,19 @@ public class RideService( await rideRepo.AddAsync(ride); await uow.CommitAsync(ct); } - catch - { - await uow.RollbackAsync(ct); - throw; - } + catch { await uow.RollbackAsync(ct); throw; } var saved = await rideRepo.GetByIdAsync(ride.Id); return ToResponse(saved!); } - public async Task OpenAsync(Guid rideId, CancellationToken ct = default) - { - var ride = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.Draft) - throw new InvalidOperationException($"Cannot open a ride in {ride.Status} status"); - - if (await rideRepo.HasOpenOrActiveRideForVehicleAsync(ride.FK_VehicleId, ride.Id)) - throw new InvalidOperationException("Vehicle already has an open or active ride"); - - await CheckDriverComplianceAsync(ride.FK_DriverProfileId); - - ride.Status = RideStatus.Open; - ride.StartedAt = DateTime.Now; - - await uow.BeginAsync(ct); - try { rideRepo.Update(ride); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(ride); - } - public async Task AssignDriverAsync(Guid rideId, Guid driverProfileId, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(rideId) ?? throw new KeyNotFoundException("Ride not found"); - if (ride.Status != RideStatus.Draft) - throw new InvalidOperationException("Driver can only be changed while the ride is in Draft status"); + if (ride.Status != RideStatus.Open) + throw new InvalidOperationException("Driver can only be changed while the ride is Open"); var driver = await driverRepo.GetByIdAsync(driverProfileId); if (driver is null || !driver.IsActive) @@ -114,31 +76,12 @@ public class RideService( return ToResponse(saved!); } - public async Task ActivateAsync(Guid rideId, ActivateRideRequest request, CancellationToken ct = default) - { - var ride = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.Open) - throw new InvalidOperationException($"Cannot activate a ride in {ride.Status} status"); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = request.Meterstart; - - await uow.BeginAsync(ct); - try { rideRepo.Update(ride); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(ride); - } - public async Task CloseAsync(Guid rideId, CloseRideRequest request, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(rideId) ?? throw new KeyNotFoundException("Ride not found"); - if (ride.Status != RideStatus.Active) + if (ride.Status != RideStatus.Open) throw new InvalidOperationException($"Cannot close a ride in {ride.Status} status"); if (request.Meterend < ride.Meterstart) @@ -157,162 +100,21 @@ public class RideService( return ToResponse(ride); } - public async Task RaiseCancelRequestAsync(Guid rideId, RaiseCancelRequest request, Guid requestedBy, CancellationToken ct = default) + public async Task CancelAsync(Guid rideId, CancelRideRequest request, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(rideId) ?? throw new KeyNotFoundException("Ride not found"); - if (ride.Status != RideStatus.Active) - throw new InvalidOperationException($"Cannot raise a cancel request for a ride in {ride.Status} status"); - - var existing = await cancelRepo.GetPendingByRideIdAsync(rideId); - if (existing is not null) - throw new InvalidOperationException("There is already a pending cancel request for this ride"); - - var cancelRequest = new RideCancelRequest - { - FK_RideId = rideId, - TypeCode = request.TypeCode, - Reason = request.Reason, - RequestedBy = requestedBy, - RequestedAt = DateTime.Now, - Status = CancelRequestStatus.Pending - }; - - ride.Status = RideStatus.CancelRequested; - - await uow.BeginAsync(ct); - try - { - await cancelRepo.AddAsync(cancelRequest); - rideRepo.Update(ride); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToCancelResponse(cancelRequest); - } - - public async Task> GetCancelRequestsAsync(CancelRequestStatus? status, int page, int pageSize) - { - var total = await cancelRepo.GetCountAsync(status); - var items = await cancelRepo.GetAllAsync(status, page, pageSize); - return new PagedResponse(page, pageSize, total, items.Select(ToCancelResponse).ToList()); - } - - public async Task ApproveCancelAsync(Guid cancelRequestId, Guid approvedBy, CancellationToken ct = default) - { - var cancelRequest = await cancelRepo.GetByIdAsync(cancelRequestId) - ?? throw new KeyNotFoundException("Cancel request not found"); - - if (cancelRequest.Status != CancelRequestStatus.Pending) - throw new InvalidOperationException("Cancel request is not pending"); - - var ride = await rideRepo.GetByIdAsync(cancelRequest.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.CancelRequested) - throw new InvalidOperationException("Ride is not in CancelRequested status"); - - await EnsureVehicleStockClearedAsync(ride.FK_VehicleId); - - cancelRequest.Status = CancelRequestStatus.Approved; - cancelRequest.ApprovedBy = approvedBy; - cancelRequest.ApprovedAt = DateTime.Now; + if (ride.Status != RideStatus.Open) + throw new InvalidOperationException($"Cannot cancel a ride in {ride.Status} status"); ride.Status = RideStatus.Cancelled; await uow.BeginAsync(ct); - try - { - cancelRepo.Update(cancelRequest); - rideRepo.Update(ride); - await uow.CommitAsync(ct); - } + try { rideRepo.Update(ride); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } - return ToCancelResponse(cancelRequest); - } - - public async Task RejectCancelAsync(Guid cancelRequestId, Guid rejectedBy, CancellationToken ct = default) - { - var cancelRequest = await cancelRepo.GetByIdAsync(cancelRequestId) - ?? throw new KeyNotFoundException("Cancel request not found"); - - if (cancelRequest.Status != CancelRequestStatus.Pending) - throw new InvalidOperationException("Cancel request is not pending"); - - var ride = await rideRepo.GetByIdAsync(cancelRequest.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.CancelRequested) - throw new InvalidOperationException("Ride is not in CancelRequested status"); - - cancelRequest.Status = CancelRequestStatus.Rejected; - cancelRequest.ApprovedBy = rejectedBy; - cancelRequest.ApprovedAt = DateTime.Now; - - // Restore to previous status: Active if ActivatedAt is set, else Open - ride.Status = ride.ActivatedAt.HasValue ? RideStatus.Active : RideStatus.Open; - - await uow.BeginAsync(ct); - try - { - cancelRepo.Update(cancelRequest); - rideRepo.Update(ride); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToCancelResponse(cancelRequest); - } - - public async Task GetCancelRequestAsync(Guid rideId) - { - var cancelRequest = await cancelRepo.GetByRideIdAsync(rideId); - return cancelRequest is null ? null : ToCancelResponse(cancelRequest); - } - - public async Task GetBreakdownAssistAsync(Guid rideId) - { - var strandedRide = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - var activeRides = await rideRepo.GetActiveRidesAsync(rideId); - var activeRideResponses = new List(); - - foreach (var ride in activeRides) - { - var stockLevels = await stockRepo.GetBalancesByLocationAsync(ride.FK_VehicleId, LocationType.Vehicle); - activeRideResponses.Add(new BreakdownAssistRideResponse( - ride.Id, - ride.FK_VehicleId, - ride.Vehicle?.NumberPlate ?? string.Empty, - ride.FK_DriverProfileId, - ride.DriverProfile?.User?.FullName ?? string.Empty, - ride.FK_RouteId, - ride.Route?.RouteName ?? string.Empty, - stockLevels.Select(b => new StockBalanceResponse( - b.FK_ItemId, - b.Item.Name, - b.LocationId, - b.LocationType, - b.Quantity, - b.UpdatedAt, - ride.Vehicle?.NumberPlate ?? string.Empty)).ToList())); - } - - var openOrders = await rideRepo.GetActiveOrdersByRouteIdAsync(strandedRide.FK_RouteId); - - return new BreakdownAssistResponse( - strandedRide.Id, - activeRideResponses, - openOrders.Select(o => new BreakdownAssistOrderResponse( - o.Id, - o.StoreId, - o.StoreName, - o.OrderDate, - o.TotalAmount)).ToList()); + return ToResponse(ride); } private async Task CheckDriverComplianceAsync(Guid driverProfileId) @@ -343,15 +145,9 @@ public class RideService( } private static RideResponse ToResponse(DeliveryRun r) => - new(r.Id, r.RideType, r.Status, + new(r.Id, r.Status, r.FK_VehicleId, r.Vehicle?.NumberPlate ?? string.Empty, r.FK_DriverProfileId, r.DriverProfile?.User?.FullName ?? string.Empty, - r.FK_RouteId, r.Route?.RouteName ?? string.Empty, - r.FK_SourceWarehouseId, r.SourceWarehouse?.Name ?? string.Empty, r.Meterstart, r.Meterend, - r.StartedAt, r.ActivatedAt, r.ClosedAt, r.CreatedAt); - - private static RideCancelRequestResponse ToCancelResponse(RideCancelRequest c) => - new(c.Id, c.FK_RideId, c.TypeCode, c.Reason, c.RequestedBy, c.RequestedAt, - c.Status, c.ApprovedBy, c.ApprovedAt); + r.StartedAt, r.ClosedAt, r.CreatedAt); } diff --git a/Distribution/Features/Sale/ISaleRepository.cs b/Distribution/Features/Sale/ISaleRepository.cs deleted file mode 100644 index 92ea633..0000000 --- a/Distribution/Features/Sale/ISaleRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Sale; - -public interface ISaleRepository -{ - Task GetByIdAsync(Guid id); - Task> GetAllAsync(Guid? rideId, IEnumerable? storeIds, int page, int pageSize); - Task GetCountAsync(Guid? rideId, IEnumerable? storeIds); - Task> GetByStoreIdAsync(Guid storeId); - Task AddAsync(Models.Sale sale); - void Update(Models.Sale sale); - void Remove(Models.Sale sale); - Task GetOrderBySaleIdAsync(Guid saleId); -} diff --git a/Distribution/Features/Sale/SaleController.cs b/Distribution/Features/Sale/SaleController.cs deleted file mode 100644 index 714b489..0000000 --- a/Distribution/Features/Sale/SaleController.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Distribution.Features.Sale; - -[ApiController] -[Route("api/sales")] -public class SaleController(SaleService service) : ControllerBase -{ - [HttpGet] - public async Task GetAll( - [FromQuery] Guid? rideId, - [FromQuery] int page = 1, - [FromQuery] int pageSize = 20) => - Ok(await service.GetAllAsync(rideId, page, pageSize)); - - [HttpGet("{id:guid}")] - public async Task GetById(Guid id) - { - var result = await service.GetByIdAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpGet("store/{storeId:guid}")] - public async Task GetByStore(Guid storeId) - { - var result = await service.GetByStoreIdAsync(storeId); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : Ok(result); - } - - [HttpPost] - public async Task Create(CreateSaleRequest request, CancellationToken ct) - { - try - { - var result = await service.CreateAsync(request, ct); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : CreatedAtAction(nameof(GetById), new { id = result.Id }, result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/cancel")] - public async Task Cancel(Guid id, CancellationToken ct) - { - try - { - var result = await service.CancelAsync(id, ct); - return result is null ? NotFound() : Ok(result); - } - catch (InvalidOperationException ex) { return Conflict(new { error = ex.Message }); } - } -} diff --git a/Distribution/Features/Sale/SaleDTOs.cs b/Distribution/Features/Sale/SaleDTOs.cs deleted file mode 100644 index 171b788..0000000 --- a/Distribution/Features/Sale/SaleDTOs.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Sale; - -public record SaleItemRequest(Guid ItemId, int Quantity, decimal? UnitPrice = null); - -public record CreateSaleRequest( - Guid StoreId, - DateTime SaleDate, - decimal TotalAmount, - bool FulfillImmediately, - Guid? RideId, - List Items, - // TEMPORARY: auth middleware doesn't attach a resolvable user yet (see testbug.md #28), so the - // caller supplies the acting user explicitly. Remove once currentUser.UserId is reliable again. - Guid? CreatedByUserId = null); - -public record SaleItemResponse(Guid ItemId, int Quantity, int QuantityFulfilled, decimal UnitPrice); - -public record SaleResponse( - Guid Id, - DateTime SaleDate, - Guid StoreId, - Guid CreatedByUserId, - Guid? RideId, - decimal TotalAmount, - SaleStatus Status, - PaymentStatus PaymentStatus, - bool FulfillImmediately, - DateTime? CompletedAt, - Guid OrderId, - OrderStatus OrderStatus, - DateTime? OrderFulfilledAt, - List Items, - bool IsActive, - DateTime CreatedAt); diff --git a/Distribution/Features/Sale/SaleRepository.cs b/Distribution/Features/Sale/SaleRepository.cs deleted file mode 100644 index 4768aba..0000000 --- a/Distribution/Features/Sale/SaleRepository.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Distribution.Data; -using Distribution.Models; -using Microsoft.EntityFrameworkCore; - -namespace Distribution.Features.Sale; - -public class SaleRepository(AppDBContext context) : ISaleRepository -{ - public async Task GetByIdAsync(Guid id) => - await context.Sales.FindAsync(id); - - public async Task> GetAllAsync(Guid? rideId, IEnumerable? storeIds, int page, int pageSize) => - await context.Sales - .Where(s => s.IsActive && - (rideId == null || s.FK_RideId == rideId) && - (storeIds == null || storeIds.Contains(s.FK_StoreId))) - .OrderByDescending(s => s.CreatedAt) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(); - - public async Task GetCountAsync(Guid? rideId, IEnumerable? storeIds) => - await context.Sales - .CountAsync(s => s.IsActive && - (rideId == null || s.FK_RideId == rideId) && - (storeIds == null || storeIds.Contains(s.FK_StoreId))); - - public async Task> GetByStoreIdAsync(Guid storeId) => - await context.Sales.Where(s => s.FK_StoreId == storeId && s.IsActive).ToListAsync(); - - public async Task AddAsync(Models.Sale sale) => - await context.Sales.AddAsync(sale); - - public void Update(Models.Sale sale) => - context.Sales.Update(sale); - - public void Remove(Models.Sale sale) - { - sale.IsActive = false; - context.Sales.Update(sale); - } - - public async Task GetOrderBySaleIdAsync(Guid saleId) => - await context.Orders.FirstOrDefaultAsync(o => o.FK_SaleId == saleId && o.IsActive); -} diff --git a/Distribution/Features/Sale/SaleService.cs b/Distribution/Features/Sale/SaleService.cs deleted file mode 100644 index 4028144..0000000 --- a/Distribution/Features/Sale/SaleService.cs +++ /dev/null @@ -1,273 +0,0 @@ -using Distribution.Features.Item; -using Distribution.Features.Order; -using Distribution.Features.PriceList; -using Distribution.Features.Ride; -using Distribution.Features.Stock; -using Distribution.Features.Store; -using Distribution.Infra.Authorization; -using Distribution.Infra.UoW; -using Distribution.Models; -using Microsoft.Extensions.Configuration; - -namespace Distribution.Features.Sale; - -public class SaleService( - ISaleRepository repo, - IOrderRepository orderRepo, - IStoreRepository storeRepo, - IItemRepository itemRepo, - PriceListService priceListService, - IStockRepository stockRepo, - IRideRepository rideRepo, - IUnitOfWork uow, - ICurrentUserService currentUser, - IScopeAccessService scopeAccess, - IConfiguration configuration) -{ - private const int GlobalScopeRoleLevel = 50; - - private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel; - - private async Task HasStoreScopeAsync(Guid storeId) - { - if (HasGlobalScope || currentUser.UserId is null) return HasGlobalScope; - return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId); - } - - private async Task ResolveUnitPriceAsync(Guid itemId, decimal? requestedUnitPrice, Models.Store store, DateTime saleDate) - { - var item = await itemRepo.GetByIdAsync(itemId); - if (item is null) return null; - - var regionId = store.Route?.FK_RegionId; - var resolution = await priceListService.ResolvePriceAsync(itemId, regionId, item.SalePrice, saleDate); - if (resolution is null) return null; - - if (!requestedUnitPrice.HasValue) return resolution.Price; - - var min = resolution.MinPrice ?? resolution.Price; - var max = resolution.Price; - if (requestedUnitPrice.Value < min || requestedUnitPrice.Value > max) return null; - - return requestedUnitPrice.Value; - } - - private static SaleResponse ToResponse(Models.Sale sale, Models.Order order, List items) => - new( - sale.Id, - sale.SaleDate, - sale.FK_StoreId, - sale.CreatedByUserId, - sale.FK_RideId, - sale.TotalAmount, - sale.Status, - sale.PaymentStatus, - sale.FulfillImmediately, - sale.CompletedAt, - order.Id, - order.Status, - order.FulfilledAt, - items.Select(i => new SaleItemResponse(i.FK_ItemId, i.Quantity, i.QuantityFulfilled, i.UnitPrice)).ToList(), - sale.IsActive, - sale.CreatedAt); - - public async Task> GetAllAsync(Guid? rideId, int page, int pageSize) - { - IEnumerable? storeIds = null; - if (!HasGlobalScope && currentUser.UserId is not null) - storeIds = await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value); - - var total = await repo.GetCountAsync(rideId, storeIds); - var sales = await repo.GetAllAsync(rideId, storeIds, page, pageSize); - - var result = new List(); - foreach (var sale in sales) - { - var order = await repo.GetOrderBySaleIdAsync(sale.Id); - if (order is null) continue; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(sale, order, items)); - } - return new PagedResponse(page, pageSize, total, result); - } - - public async Task GetByIdAsync(Guid id) - { - var sale = await repo.GetByIdAsync(id); - if (sale is null || !sale.IsActive) return null; - if (!await HasStoreScopeAsync(sale.FK_StoreId)) return null; - - var order = await repo.GetOrderBySaleIdAsync(id); - if (order is null) return null; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - return ToResponse(sale, order, items); - } - - public async Task?> GetByStoreIdAsync(Guid storeId) - { - if (!await HasStoreScopeAsync(storeId)) return null; - - var sales = await repo.GetByStoreIdAsync(storeId); - var result = new List(); - foreach (var sale in sales) - { - var order = await repo.GetOrderBySaleIdAsync(sale.Id); - if (order is null) continue; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(sale, order, items)); - } - return result; - } - - public async Task CancelAsync(Guid id, CancellationToken ct = default) - { - // TEMPORARY: see CreateAsync — store-scope enforcement depends on the broken auth - // middleware (testbug.md #28) and would reject every cancel. Skipped for now. - var sale = await repo.GetByIdAsync(id); - if (sale is null || !sale.IsActive) return null; - if (sale.Status == SaleStatus.Cancelled) - throw new InvalidOperationException("Sale is already cancelled"); - - sale.Status = SaleStatus.Cancelled; - - await uow.BeginAsync(ct); - try { repo.Update(sale); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - var order = await repo.GetOrderBySaleIdAsync(id); - if (order is null) return null; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - return ToResponse(sale, order, items); - } - - public async Task CreateAsync(CreateSaleRequest request, CancellationToken ct = default) - { - // TEMPORARY: store-scope enforcement and currentUser resolution both depend on the broken - // auth middleware (see testbug.md #28) — currentUser.UserId/RoleLevel are always unset, so - // both checks would reject every sale. Skipped for now; restore once auth is fixed. - var userId = currentUser.UserId ?? request.CreatedByUserId - ?? throw new InvalidOperationException("CreatedByUserId is required while auth is unavailable"); - var store = await storeRepo.GetByIdWithRegionAsync(request.StoreId) - ?? throw new InvalidOperationException("Store not found"); - if (!store.IsActive) - throw new InvalidOperationException("Store is inactive"); - - if (store.KycStatus != KycStatus.Verified) - { - var threshold = configuration.GetValue("StoreManagement:UnverifiedKycOrderThreshold"); - if (request.TotalAmount > threshold) - throw new InvalidOperationException( - $"Store KYC is not verified — sale amount ({request.TotalAmount}) exceeds the unverified-store threshold ({threshold})"); - } - - var sale = new Models.Sale - { - FK_StoreId = request.StoreId, - SaleDate = request.SaleDate, - CreatedByUserId = userId, - FK_RideId = request.RideId, - FulfillImmediately = request.FulfillImmediately - }; - - var orderItems = new List(); - foreach (var item in request.Items) - { - var unitPrice = await ResolveUnitPriceAsync(item.ItemId, item.UnitPrice, store, request.SaleDate) - ?? throw new InvalidOperationException( - $"Could not resolve a price for item {item.ItemId} on {request.SaleDate:yyyy-MM-dd} — check the item exists, an active price list covers this date/region, and any supplied unit price is within its min/max range"); - - orderItems.Add(new Models.OrderItem - { - FK_ItemId = item.ItemId, - Quantity = item.Quantity, - UnitPrice = unitPrice - }); - } - - var order = new Models.Order - { - FK_SaleId = sale.Id, - FK_StoreId = request.StoreId, - OrderDate = request.SaleDate, - }; - - foreach (var orderItem in orderItems) - orderItem.FK_OrderId = order.Id; - - // For a van sale against a specific ride, sell whatever quantity is actually on that - // vehicle instead of rejecting the whole sale over one short item — the sale is always a - // clean, completed sale of what's handed over, never a "partially fulfilled" order. - Guid? vehicleId = null; - if (request.FulfillImmediately && request.RideId.HasValue) - { - var ride = await rideRepo.GetByIdAsync(request.RideId.Value) - ?? throw new InvalidOperationException("Ride not found"); - vehicleId = ride.FK_VehicleId; - - foreach (var item in orderItems) - { - var balance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId.Value); - item.Quantity = Math.Min(item.Quantity, (int)(balance?.Quantity ?? 0)); - } - } - - foreach (var item in orderItems) - item.QuantityFulfilled = request.FulfillImmediately ? item.Quantity : 0; - - if (request.FulfillImmediately) - { - sale.Status = SaleStatus.Completed; - sale.CompletedAt = DateTime.Now; - order.Status = OrderStatus.Fulfilled; - order.FulfilledAt = DateTime.Now; - } - else - { - sale.Status = SaleStatus.Pending; - order.Status = OrderStatus.Pending; - } - - sale.TotalAmount = orderItems.Sum(i => i.Quantity * i.UnitPrice); - order.TotalAmount = sale.TotalAmount; - - await uow.BeginAsync(ct); - try - { - await repo.AddAsync(sale); - await orderRepo.AddAsync(order); - await orderRepo.AddItemsAsync(orderItems); - - if (vehicleId.HasValue) - { - foreach (var item in orderItems.Where(i => i.QuantityFulfilled > 0)) - { - var balance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId.Value); - balance!.Quantity -= item.QuantityFulfilled; - balance.UpdatedAt = DateTime.Now; - stockRepo.UpdateBalance(balance); - - await stockRepo.AddMovementAsync(new StockMovement - { - FK_ItemId = item.FK_ItemId, - FromLocationId = vehicleId.Value, - FromLocationType = LocationType.Vehicle, - ToLocationId = StockService.ExternalLocationId, - ToLocationType = LocationType.External, - Quantity = item.QuantityFulfilled, - Type = MovementType.Sale, - ReferenceId = order.Id - }); - } - } - - await uow.CommitAsync(ct); - } - catch - { - await uow.RollbackAsync(ct); - throw; - } - - return ToResponse(sale, order, orderItems); - } -} diff --git a/Distribution/Features/Scheme/SchemeDTOs.cs b/Distribution/Features/Scheme/SchemeDTOs.cs index 5e49bb7..28ec165 100644 --- a/Distribution/Features/Scheme/SchemeDTOs.cs +++ b/Distribution/Features/Scheme/SchemeDTOs.cs @@ -99,7 +99,7 @@ public record SchemeEligibilityResponse( public record SchemeRedemptionResponse( Guid Id, Guid SchemeId, - Guid? OrderId, + Guid? ShopPOId, decimal? DiscountAmount, Guid? FreeItemId, string? FreeItemName, diff --git a/Distribution/Features/Scheme/SchemeRepository.cs b/Distribution/Features/Scheme/SchemeRepository.cs index 123ca69..2d22e62 100644 --- a/Distribution/Features/Scheme/SchemeRepository.cs +++ b/Distribution/Features/Scheme/SchemeRepository.cs @@ -42,15 +42,15 @@ public class SchemeRepository(AppDBContext context) : ISchemeRepository public async Task> GetRedemptionsAsync(Guid schemeId) => await context.SchemeRedemptions .Include(r => r.FreeItem) - .Include(r => r.Order) + .Include(r => r.ShopPO) .Where(r => r.FK_SchemeId == schemeId) .ToListAsync(); public async Task AddRedemptionAsync(Models.SchemeRedemption entity) => await context.SchemeRedemptions.AddAsync(entity); - public async Task HasRedemptionAsync(Guid schemeId, Guid orderId) => - await context.SchemeRedemptions.AnyAsync(r => r.FK_SchemeId == schemeId && r.FK_OrderId == orderId); + public async Task HasRedemptionAsync(Guid schemeId, Guid shopPOId) => + await context.SchemeRedemptions.AnyAsync(r => r.FK_SchemeId == schemeId && r.FK_ShopPOId == shopPOId); public async Task GetBundleComponentAsync(Guid schemeId, Guid itemId) => await context.SchemeBundleComponents diff --git a/Distribution/Features/Scheme/SchemeService.cs b/Distribution/Features/Scheme/SchemeService.cs index ebf4329..e17f810 100644 --- a/Distribution/Features/Scheme/SchemeService.cs +++ b/Distribution/Features/Scheme/SchemeService.cs @@ -1,6 +1,6 @@ using System.Text.Json; using Distribution.Features.Item; -using Distribution.Features.Order; +using Distribution.Features.ShopPO; using Distribution.Features.Stock; using Distribution.Features.Store; using Distribution.Infra.UoW; @@ -10,7 +10,7 @@ namespace Distribution.Features.Scheme; public class SchemeService( ISchemeRepository repo, - IOrderRepository orderRepo, + IShopPORepository shopPORepo, IItemRepository itemRepo, IStoreRepository storeRepo, IStockRepository stockRepo, @@ -27,7 +27,7 @@ public class SchemeService( s.DateRangeFrom, s.DateRangeTo, s.AgentLimitExempt, s.BaselineExpectedSales, s.IsActive, s.CreatedAt); private static SchemeRedemptionResponse ToRedemptionResponse(SchemeRedemption r) => - new(r.Id, r.FK_SchemeId, r.FK_OrderId, r.DiscountAmount, r.FK_FreeItemId, r.FreeItem?.Name, + new(r.Id, r.FK_SchemeId, r.FK_ShopPOId, r.DiscountAmount, r.FK_FreeItemId, r.FreeItem?.Name, r.FreeQty, r.FreeItemCostValue, r.RedeemedAt); // ── CRUD ─────────────────────────────────────────────────────────────── @@ -243,17 +243,17 @@ public class SchemeService( return (await GetByIdAsync(schemeId))!; } - // ── evaluateSchemeEligibility(storeId, orderId) ────────────────────────── + // ── evaluateSchemeEligibility(storeId, shopPOId) ────────────────────────── - public async Task?> EvaluateEligibilityAsync(Guid storeId, Guid orderId) + public async Task?> EvaluateEligibilityAsync(Guid storeId, Guid shopPOId) { var store = await storeRepo.GetByIdWithRegionAsync(storeId); if (store is null || !store.IsActive) return null; - var order = await orderRepo.GetByIdAsync(orderId); - if (order is null || !order.IsActive) return null; + var shopPO = await shopPORepo.GetByIdAsync(shopPOId); + if (shopPO is null || !shopPO.IsActive) return null; - var orderItems = await orderRepo.GetItemsByOrderIdAsync(orderId); + var items = await shopPORepo.GetActiveItemsByShopPOIdAsync(shopPOId); var regionId = store.Route?.FK_RegionId; var candidates = (await repo.GetAllAsync()).Where(s => s.IsActive); @@ -266,21 +266,21 @@ public class SchemeService( if (!string.IsNullOrEmpty(scheme.EligibleSegment) && !string.Equals(scheme.EligibleSegment, store.Segment, StringComparison.OrdinalIgnoreCase)) continue; - if (order.OrderDate < scheme.DateRangeFrom || order.OrderDate > scheme.DateRangeTo) + if (shopPO.CreatedAt < scheme.DateRangeFrom || shopPO.CreatedAt > scheme.DateRangeTo) continue; - result.Add(EvaluateRule(scheme, orderItems)); + result.Add(EvaluateRule(scheme, items)); } return result; } /// - /// Scope-only check (region, segment, date range as of today) with no order to evaluate line + /// Scope-only check (region, segment, date range as of today) with no ShopPO to evaluate line /// items against — used by Store Management's `checkStoreSchemeEligibility(storeId, schemeId)` /// (12_store_management.md), which has no order context. Returns null if the store or scheme /// doesn't exist; otherwise (Eligible, Reason) — Eligible here means "in scope for this store", - /// not "this order's items satisfy the rule" (use EvaluateEligibilityAsync for that). + /// not "this ShopPO's items satisfy the rule" (use EvaluateEligibilityAsync for that). /// public async Task<(bool Eligible, string? Reason)?> CheckStoreScopeEligibilityAsync(Guid storeId, Guid schemeId) { @@ -305,7 +305,7 @@ public class SchemeService( return (true, null); } - private static SchemeEligibilityResponse EvaluateRule(Models.Scheme scheme, List orderItems) + private static SchemeEligibilityResponse EvaluateRule(Models.Scheme scheme, List items) { switch (scheme.RuleType) { @@ -316,10 +316,10 @@ public class SchemeService( return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, "Scheme has no free-goods rule configured.", null, null, null); - var boughtQty = orderItems.Where(i => i.FK_ItemId == scheme.FK_TriggerItemId).Sum(i => i.Quantity); + var boughtQty = items.Where(i => i.FK_ItemId == scheme.FK_TriggerItemId).Sum(i => i.Quantity); if (boughtQty < scheme.TriggerQty) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, - $"Requires {scheme.TriggerQty} of the trigger item; order has {boughtQty}.", null, null, null); + $"Requires {scheme.TriggerQty} of the trigger item; ShopPO has {boughtQty}.", null, null, null); var multiplier = boughtQty / scheme.TriggerQty.Value; return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, @@ -332,11 +332,11 @@ public class SchemeService( "Scheme has no bundle components or free-goods payout configured.", null, null, null); var missing = scheme.BundleComponents - .Where(c => orderItems.Where(i => i.FK_ItemId == c.FK_ItemId).Sum(i => i.Quantity) < c.Qty) + .Where(c => items.Where(i => i.FK_ItemId == c.FK_ItemId).Sum(i => i.Quantity) < c.Qty) .ToList(); if (missing.Count > 0) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, - "Order is missing required bundle components.", null, null, null); + "ShopPO is missing required bundle components.", null, null, null); return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, null, scheme.FK_FreeItemId, scheme.FreeQty); @@ -346,7 +346,7 @@ public class SchemeService( if (string.IsNullOrEmpty(scheme.RuleConfig)) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, "Scheme has no RuleConfig.", null, null, null); var cfg = JsonSerializer.Deserialize(scheme.RuleConfig, JsonOptions)!; - var orderTotal = orderItems.Sum(i => i.Quantity * i.UnitPrice); + var orderTotal = items.Sum(i => i.Quantity * i.UnitPrice); return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, Math.Round(orderTotal * cfg.DiscountPercent / 100m, 2), null, null); } @@ -355,12 +355,12 @@ public class SchemeService( if (string.IsNullOrEmpty(scheme.RuleConfig)) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, "Scheme has no RuleConfig.", null, null, null); var cfg = JsonSerializer.Deserialize(scheme.RuleConfig, JsonOptions)!; - var orderTotal = orderItems.Sum(i => i.Quantity * i.UnitPrice); + var orderTotal = items.Sum(i => i.Quantity * i.UnitPrice); var tier = cfg.Tiers.Where(t => orderTotal >= t.MinOrderAmount) .OrderByDescending(t => t.MinOrderAmount).FirstOrDefault(); if (tier is null) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, - "Order total does not meet any slab threshold.", null, null, null); + "ShopPO total does not meet any slab threshold.", null, null, null); return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, Math.Round(orderTotal * tier.DiscountPercent / 100m, 2), null, null); @@ -370,32 +370,32 @@ public class SchemeService( } } - // ── applySchemeDiscount(orderId, schemeId) ─────────────────────────────── + // ── applySchemeDiscount(shopPOId, schemeId) ─────────────────────────────── - public async Task ApplySchemeAsync(Guid orderId, Guid schemeId, CancellationToken ct = default) + public async Task ApplySchemeAsync(Guid shopPOId, Guid schemeId, CancellationToken ct = default) { var scheme = await repo.GetByIdAsync(schemeId); if (scheme is null || !scheme.IsActive) return null; - var order = await orderRepo.GetByIdAsync(orderId); - if (order is null || !order.IsActive) return null; + var shopPO = await shopPORepo.GetByIdAsync(shopPOId); + if (shopPO is null || !shopPO.IsActive) return null; - if (await repo.HasRedemptionAsync(schemeId, orderId)) - throw new InvalidOperationException("This scheme has already been redeemed against this order."); + if (await repo.HasRedemptionAsync(schemeId, shopPOId)) + throw new InvalidOperationException("This scheme has already been redeemed against this ShopPO."); - var orderItems = await orderRepo.GetItemsByOrderIdAsync(orderId); - var eligibility = EvaluateRule(scheme, orderItems); + var items = await shopPORepo.GetActiveItemsByShopPOIdAsync(shopPOId); + var eligibility = EvaluateRule(scheme, items); if (!eligibility.Eligible) - throw new InvalidOperationException(eligibility.Reason ?? "Order is not eligible for this scheme."); + throw new InvalidOperationException(eligibility.Reason ?? "ShopPO is not eligible for this scheme."); var redemption = new SchemeRedemption { FK_SchemeId = schemeId, - FK_OrderId = orderId, + FK_ShopPOId = shopPOId, DiscountAmount = eligibility.DiscountAmount }; - var newOrderItems = new List(); + var newItems = new List(); if (eligibility.FreeItemId.HasValue && eligibility.FreeQty is > 0) { @@ -406,9 +406,9 @@ public class SchemeService( if (availableQty < eligibility.FreeQty.Value) throw new InvalidOperationException($"Insufficient stock of '{freeItem.Sku}' to fulfil the free-goods scheme."); - newOrderItems.Add(new OrderItem + newItems.Add(new ShopPOItem { - FK_OrderId = orderId, + FK_ShopPOId = shopPOId, FK_ItemId = freeItem.Id, Quantity = (int)eligibility.FreeQty.Value, UnitPrice = 0m @@ -422,7 +422,7 @@ public class SchemeService( await uow.BeginAsync(ct); try { - if (newOrderItems.Count > 0) await orderRepo.AddItemsAsync(newOrderItems); + if (newItems.Count > 0) await shopPORepo.AddItemsAsync(newItems); await repo.AddRedemptionAsync(redemption); await uow.CommitAsync(ct); } @@ -457,8 +457,8 @@ public class SchemeService( var spend = await GetSpendAsync(schemeId); var actualSales = redemptions - .Where(r => r.Order is not null) - .Select(r => r.Order!) + .Where(r => r.ShopPO is not null) + .Select(r => r.ShopPO!) .Distinct() .Sum(o => o.TotalAmount); diff --git a/Distribution/Features/ShopPO/IShopPORepository.cs b/Distribution/Features/ShopPO/IShopPORepository.cs new file mode 100644 index 0000000..4a15739 --- /dev/null +++ b/Distribution/Features/ShopPO/IShopPORepository.cs @@ -0,0 +1,18 @@ +using Distribution.Models; + +namespace Distribution.Features.ShopPO; + +public interface IShopPORepository +{ + Task GetByIdAsync(Guid id); + Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize); + Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed); + Task> GetConfirmedWithoutInvoiceAsync(Guid? agentId, Guid? routeId, Guid? shopId); + Task> GetActiveItemsByShopPOIdAsync(Guid shopPOId); + Task> GetByStoreIdAsync(Guid storeId); + Task AddAsync(Models.ShopPO entity); + void Update(Models.ShopPO entity); + void Remove(Models.ShopPO entity); + Task AddItemsAsync(IEnumerable items); + Task ReplaceItemsAsync(Guid shopPOId, List newItems); +} diff --git a/Distribution/Features/ShopPO/ShopPOController.cs b/Distribution/Features/ShopPO/ShopPOController.cs new file mode 100644 index 0000000..a7fb4c7 --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPOController.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Distribution.Features.ShopPO; + +[ApiController] +[Route("api/shop-pos")] +public class ShopPOController(ShopPOService service) : ControllerBase +{ + [HttpGet] + public async Task GetAll( + [FromQuery] Guid? agentId, + [FromQuery] Guid? routeId, + [FromQuery] Guid? shopId, + [FromQuery] bool? confirmed, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20) + { + var result = await service.GetAllAsync(agentId, routeId, shopId, confirmed, page, pageSize); + return Ok(result); + } + + [HttpGet("{id:guid}")] + public async Task GetById(Guid id) + { + var result = await service.GetByIdAsync(id); + return result is null ? NotFound() : Ok(result); + } +} diff --git a/Distribution/Features/ShopPO/ShopPODTOs.cs b/Distribution/Features/ShopPO/ShopPODTOs.cs new file mode 100644 index 0000000..2eb2604 --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPODTOs.cs @@ -0,0 +1,24 @@ +using Distribution.Models; + +namespace Distribution.Features.ShopPO; + +public record CreateShopPORequest(Guid StoreId, List Items); +public record ShopPOItemRequest(Guid ItemId, int Quantity, decimal? UnitPrice = null); +public record UpdateShopPOItemsRequest(List Items); + +public record ShopPOItemResponse(Guid Id, Guid ItemId, string ItemName, int Quantity, int QuantityFulfilled, decimal UnitPrice, bool IsActive); + +public record ShopPOResponse( + Guid Id, + Guid StoreId, + string StoreName, + Guid RaisedById, + Guid? InvoiceId, + decimal TotalAmount, + ShopPOStatus Status, + DateTime? ConfirmedAt, + Guid? ConfirmedBy, + DateTime? FulfilledAt, + List Items, + bool IsActive, + DateTime CreatedAt); diff --git a/Distribution/Features/ShopPO/ShopPORepository.cs b/Distribution/Features/ShopPO/ShopPORepository.cs new file mode 100644 index 0000000..2933fdc --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPORepository.cs @@ -0,0 +1,91 @@ +using Distribution.Data; +using Distribution.Models; +using Microsoft.EntityFrameworkCore; + +namespace Distribution.Features.ShopPO; + +public class ShopPORepository(AppDBContext context) : IShopPORepository +{ + public async Task GetByIdAsync(Guid id) => + await context.ShopPOs + .Include(p => p.Store) + .Include(p => p.Items.Where(i => i.IsActive)) + .ThenInclude(i => i.Item) + .FirstOrDefaultAsync(p => p.Id == id && p.IsActive); + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize) => + await context.ShopPOs + .Include(p => p.Store) + .Where(p => p.IsActive + && (agentId == null || p.RaisedById == agentId) + && (routeId == null || p.Store.FK_RouteId == routeId) + && (shopId == null || p.FK_StoreId == shopId) + && (confirmed == null || (confirmed == true ? p.ConfirmedAt != null : p.ConfirmedAt == null))) + .OrderByDescending(p => p.CreatedAt) + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + public async Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed) => + await context.ShopPOs + .Include(p => p.Store) + .CountAsync(p => p.IsActive + && (agentId == null || p.RaisedById == agentId) + && (routeId == null || p.Store.FK_RouteId == routeId) + && (shopId == null || p.FK_StoreId == shopId) + && (confirmed == null || (confirmed == true ? p.ConfirmedAt != null : p.ConfirmedAt == null))); + + public async Task> GetConfirmedWithoutInvoiceAsync(Guid? agentId, Guid? routeId, Guid? shopId) => + await context.ShopPOs + .Include(p => p.Store) + .Include(p => p.Items.Where(i => i.IsActive)) + .Where(p => p.IsActive + && p.ConfirmedAt != null + && p.InvoiceId == null + && (agentId == null || p.RaisedById == agentId) + && (routeId == null || p.Store.FK_RouteId == routeId) + && (shopId == null || p.FK_StoreId == shopId)) + .ToListAsync(); + + public async Task> GetActiveItemsByShopPOIdAsync(Guid shopPOId) => + await context.ShopPOItems + .Include(i => i.Item) + .Where(i => i.FK_ShopPOId == shopPOId && i.IsActive) + .ToListAsync(); + + public async Task> GetByStoreIdAsync(Guid storeId) => + await context.ShopPOs + .Include(p => p.Items.Where(i => i.IsActive)) + .Where(p => p.FK_StoreId == storeId && p.IsActive) + .ToListAsync(); + + public async Task AddAsync(Models.ShopPO entity) => + await context.ShopPOs.AddAsync(entity); + + public void Update(Models.ShopPO entity) => + context.ShopPOs.Update(entity); + + public void Remove(Models.ShopPO entity) + { + entity.IsActive = false; + context.ShopPOs.Update(entity); + } + + public async Task AddItemsAsync(IEnumerable items) => + await context.ShopPOItems.AddRangeAsync(items); + + public async Task ReplaceItemsAsync(Guid shopPOId, List newItems) + { + var current = await context.ShopPOItems + .Where(i => i.FK_ShopPOId == shopPOId && i.IsActive) + .ToListAsync(); + + foreach (var item in current) + { + item.IsActive = false; + context.ShopPOItems.Update(item); + } + + await context.ShopPOItems.AddRangeAsync(newItems); + } +} diff --git a/Distribution/Features/ShopPO/ShopPOService.cs b/Distribution/Features/ShopPO/ShopPOService.cs new file mode 100644 index 0000000..1f5fda0 --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPOService.cs @@ -0,0 +1,32 @@ +using Distribution.Features.Stock; +using Distribution.Infra.UoW; +using Distribution.Models; + +namespace Distribution.Features.ShopPO; + +public class ShopPOService( + IShopPORepository repo, + IUnitOfWork uow) +{ + private static ShopPOResponse ToResponse(Models.ShopPO p) => + new(p.Id, p.FK_StoreId, p.Store?.StoreName ?? string.Empty, + p.RaisedById, p.InvoiceId, p.TotalAmount, p.Status, + p.ConfirmedAt, p.ConfirmedBy, p.FulfilledAt, + p.Items.Where(i => i.IsActive).Select(i => + new ShopPOItemResponse(i.Id, i.FK_ItemId, i.Item?.Name ?? string.Empty, + i.Quantity, i.QuantityFulfilled, i.UnitPrice, i.IsActive)).ToList(), + p.IsActive, p.CreatedAt); + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize) + { + var total = await repo.GetCountAsync(agentId, routeId, shopId, confirmed); + var items = await repo.GetAllAsync(agentId, routeId, shopId, confirmed, page, pageSize); + return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); + } + + public async Task GetByIdAsync(Guid id) + { + var po = await repo.GetByIdAsync(id); + return po is null ? null : ToResponse(po); + } +} diff --git a/Distribution/Features/Store/IStoreRepository.cs b/Distribution/Features/Store/IStoreRepository.cs index 6633023..dc3f81b 100644 --- a/Distribution/Features/Store/IStoreRepository.cs +++ b/Distribution/Features/Store/IStoreRepository.cs @@ -12,5 +12,5 @@ public interface IStoreRepository Task AddAsync(Models.Store entity); void Update(Models.Store entity); void Remove(Models.Store entity); - Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive); + Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive); } diff --git a/Distribution/Features/Store/StoreRepository.cs b/Distribution/Features/Store/StoreRepository.cs index 6e28d24..db56e9a 100644 --- a/Distribution/Features/Store/StoreRepository.cs +++ b/Distribution/Features/Store/StoreRepository.cs @@ -48,8 +48,8 @@ public class StoreRepository(AppDBContext context) : IStoreRepository context.Stores.Update(entity); } - public async Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive) => - await context.Orders - .Where(o => o.FK_StoreId == storeId && o.IsActive && o.OrderDate >= periodStart && o.OrderDate < periodEndExclusive) + public async Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive) => + await context.ShopPOs + .Where(o => o.FK_StoreId == storeId && o.IsActive && o.CreatedAt >= periodStart && o.CreatedAt < periodEndExclusive) .ToListAsync(); } diff --git a/Distribution/Features/Store/StoreService.cs b/Distribution/Features/Store/StoreService.cs index bcb1c72..e7a2383 100644 --- a/Distribution/Features/Store/StoreService.cs +++ b/Distribution/Features/Store/StoreService.cs @@ -268,6 +268,6 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe periodStart.ToString("yyyy-MM"), orders.Count, orders.Sum(o => o.TotalAmount), - orders.Count == 0 ? null : orders.Max(o => o.OrderDate)); + orders.Count == 0 ? null : orders.Max(o => o.CreatedAt)); } } diff --git a/Distribution/Features/SysConfig/ISysConfigRepository.cs b/Distribution/Features/SysConfig/ISysConfigRepository.cs new file mode 100644 index 0000000..73cc902 --- /dev/null +++ b/Distribution/Features/SysConfig/ISysConfigRepository.cs @@ -0,0 +1,8 @@ +namespace Distribution.Features.SysConfig; + +public interface ISysConfigRepository +{ + Task GetByKeyAsync(string key); + Task> GetAllAsync(); + Task UpsertAsync(Models.SysConfig entity); +} diff --git a/Distribution/Features/SysConfig/SysConfigController.cs b/Distribution/Features/SysConfig/SysConfigController.cs new file mode 100644 index 0000000..a2571bc --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigController.cs @@ -0,0 +1,53 @@ +using Distribution.Infra.Authorization; +using Distribution.Models; +using Microsoft.AspNetCore.Mvc; + +namespace Distribution.Features.SysConfig; + +[ApiController] +[Route("api/sys-config")] +public class SysConfigController(SysConfigService service, ICurrentUserService currentUser) : ControllerBase +{ + [HttpGet] + public async Task GetAll() => + Ok(await service.GetAllAsync()); + + // Typed shortcut — must be declared before {key} to take precedence + [HttpGet("invoice-creation-mode")] + public async Task GetInvoiceCreationMode() + { + var mode = await service.GetInvoiceCreationModeAsync(); + return Ok(new { Mode = mode }); + } + + [HttpPut("invoice-creation-mode")] + public async Task SetInvoiceCreationMode(SetInvoiceCreationModeRequest request, CancellationToken ct) + { + var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); + try + { + var result = await service.SetAsync(SysConfigService.KeyInvoiceCreationMode, request.Mode.ToString(), userId, ct); + return Ok(result); + } + catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } + } + + [HttpGet("{key}")] + public async Task GetByKey(string key) + { + var result = await service.GetByKeyAsync(key); + return result is null ? NotFound() : Ok(result); + } + + [HttpPut("{key}")] + public async Task Set(string key, SetSysConfigRequest request, CancellationToken ct) + { + var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); + try + { + var result = await service.SetAsync(key, request.Value, userId, ct); + return Ok(result); + } + catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } + } +} diff --git a/Distribution/Features/SysConfig/SysConfigDTOs.cs b/Distribution/Features/SysConfig/SysConfigDTOs.cs new file mode 100644 index 0000000..6084673 --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigDTOs.cs @@ -0,0 +1,9 @@ +using Distribution.Models; + +namespace Distribution.Features.SysConfig; + +public record SysConfigResponse(string Key, string Value, DateTime UpdatedAt, Guid? UpdatedBy); + +public record SetSysConfigRequest(string Value); + +public record SetInvoiceCreationModeRequest(InvoiceCreationMode Mode); diff --git a/Distribution/Features/SysConfig/SysConfigRepository.cs b/Distribution/Features/SysConfig/SysConfigRepository.cs new file mode 100644 index 0000000..f5282d2 --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigRepository.cs @@ -0,0 +1,29 @@ +using Distribution.Data; +using Microsoft.EntityFrameworkCore; + +namespace Distribution.Features.SysConfig; + +public class SysConfigRepository(AppDBContext context) : ISysConfigRepository +{ + public async Task GetByKeyAsync(string key) => + await context.SysConfigs.FindAsync(key); + + public async Task> GetAllAsync() => + await context.SysConfigs.OrderBy(c => c.Key).ToListAsync(); + + public async Task UpsertAsync(Models.SysConfig entity) + { + var existing = await context.SysConfigs.FindAsync(entity.Key); + if (existing is null) + { + await context.SysConfigs.AddAsync(entity); + } + else + { + existing.Value = entity.Value; + existing.UpdatedAt = entity.UpdatedAt; + existing.UpdatedBy = entity.UpdatedBy; + context.SysConfigs.Update(existing); + } + } +} diff --git a/Distribution/Features/SysConfig/SysConfigService.cs b/Distribution/Features/SysConfig/SysConfigService.cs new file mode 100644 index 0000000..397d53c --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigService.cs @@ -0,0 +1,67 @@ +using Distribution.Infra.UoW; +using Distribution.Models; + +namespace Distribution.Features.SysConfig; + +public class SysConfigService(ISysConfigRepository repo, IUnitOfWork uow) +{ + public const string KeyInvoiceCreationMode = "InvoiceCreationMode"; + + public async Task> GetAllAsync() + { + var configs = await repo.GetAllAsync(); + return configs.Select(ToResponse).ToList(); + } + + public async Task GetByKeyAsync(string key) + { + var config = await repo.GetByKeyAsync(key); + return config is null ? null : ToResponse(config); + } + + public async Task SetAsync(string key, string value, Guid userId, CancellationToken ct = default) + { + ValidateValue(key, value); + + var config = new Models.SysConfig + { + Key = key, + Value = value, + UpdatedAt = DateTime.Now, + UpdatedBy = userId + }; + + await uow.BeginAsync(ct); + try + { + await repo.UpsertAsync(config); + await uow.CommitAsync(ct); + } + catch { await uow.RollbackAsync(ct); throw; } + + var saved = await repo.GetByKeyAsync(key); + return ToResponse(saved!); + } + + /// + /// Returns the current InvoiceCreationMode, defaulting to ModeB if not configured. + /// ModeA = invoice auto-created on ShopPO confirmation. + /// ModeB = invoice created as a separate explicit step. + /// + public async Task GetInvoiceCreationModeAsync() + { + var config = await repo.GetByKeyAsync(KeyInvoiceCreationMode); + if (config is null) return InvoiceCreationMode.ModeB; + return Enum.TryParse(config.Value, out var mode) ? mode : InvoiceCreationMode.ModeB; + } + + private static void ValidateValue(string key, string value) + { + if (key == KeyInvoiceCreationMode && !Enum.TryParse(value, out _)) + throw new InvalidOperationException( + $"Invalid value '{value}' for '{key}'. Allowed values: {string.Join(", ", Enum.GetNames())}."); + } + + private static SysConfigResponse ToResponse(Models.SysConfig c) => + new(c.Key, c.Value, c.UpdatedAt, c.UpdatedBy); +} diff --git a/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.Designer.cs b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.Designer.cs new file mode 100644 index 0000000..c4c191f --- /dev/null +++ b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.Designer.cs @@ -0,0 +1,4026 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917034841_RefactorSalesToShopPOAndInvoice")] + partial class RefactorSalesToShopPOAndInvoice + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedAt") + .HasColumnType("datetime(6)"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RequestedAt") + .HasColumnType("datetime(6)"); + + b.Property("RequestedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TypeCode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("RideCancelRequests"); + + b.HasData( + new + { + Id = new Guid("65000000-0000-0000-0000-000000000001"), + ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), + ApprovedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + Reason = "Reported minor engine issue, resolved after inspection", + RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), + RequestedBy = new Guid("29000000-0000-0000-0000-000000000005"), + Status = 2, + TypeCode = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs new file mode 100644 index 0000000..468488d --- /dev/null +++ b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs @@ -0,0 +1,944 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Distribution.Migrations +{ + /// + public partial class RefactorSalesToShopPOAndInvoice : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + DropForeignKeyIfExists(migrationBuilder, "DeliveryRuns", "FK_DeliveryRuns_Routes_FK_RouteId"); + DropForeignKeyIfExists(migrationBuilder, "DeliveryRuns", "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId"); + + DropForeignKeyIfExists(migrationBuilder, "DeliveryTasks", "FK_DeliveryTasks_Orders_FK_OrderId"); + DropForeignKeyIfExists(migrationBuilder, "LoadingSheetItems", "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId"); + DropForeignKeyIfExists(migrationBuilder, "LoadingSheets", "FK_LoadingSheets_Warehouses_FK_SourceWarehouseId"); + DropForeignKeyIfExists(migrationBuilder, "Payments", "FK_Payments_Sales_FK_SaleId"); + DropForeignKeyIfExists(migrationBuilder, "Payments", "FK_Payments_Stores_FK_StoreId"); + DropForeignKeyIfExists(migrationBuilder, "SaleReturns", "FK_SaleReturns_Orders_FK_OrderId"); + DropForeignKeyIfExists(migrationBuilder, "SchemeRedemptions", "FK_SchemeRedemptions_Orders_FK_OrderId"); + + migrationBuilder.DropTable( + name: "OrderItems"); + + migrationBuilder.DropTable( + name: "Orders"); + + migrationBuilder.DropTable( + name: "Sales"); + + DropIndexIfExists(migrationBuilder, "Payments", "IX_Payments_FK_SaleId"); + DropIndexIfExists(migrationBuilder, "LoadingSheets", "IX_LoadingSheets_FK_SourceWarehouseId"); + DropIndexIfExists(migrationBuilder, "DeliveryRuns", "IX_DeliveryRuns_FK_RouteId"); + DropIndexIfExists(migrationBuilder, "DeliveryRuns", "IX_DeliveryRuns_FK_SourceWarehouseId"); + + DropColumnIfExists(migrationBuilder, "Payments", "FK_SaleId"); + DropColumnIfExists(migrationBuilder, "LoadingSheets", "DispatchConfirmedAt"); + DropColumnIfExists(migrationBuilder, "LoadingSheets", "DispatchConfirmedBy"); + DropColumnIfExists(migrationBuilder, "LoadingSheetItems", "QuantityReceived"); + DropColumnIfExists(migrationBuilder, "LoadingSheetItems", "QuantityResolved"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "ActivatedAt"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "FK_RouteId"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "FK_SourceWarehouseId"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "RideType"); + + migrationBuilder.RenameColumn( + name: "FK_OrderId", + table: "SchemeRedemptions", + newName: "FK_ShopPOId"); + + migrationBuilder.RenameIndex( + name: "IX_SchemeRedemptions_FK_OrderId", + table: "SchemeRedemptions", + newName: "IX_SchemeRedemptions_FK_ShopPOId"); + + migrationBuilder.RenameColumn( + name: "FK_OrderId", + table: "SaleReturns", + newName: "FK_ShopPOId"); + + migrationBuilder.RenameIndex( + name: "IX_SaleReturns_FK_OrderId", + table: "SaleReturns", + newName: "IX_SaleReturns_FK_ShopPOId"); + + migrationBuilder.RenameColumn( + name: "FK_StoreId", + table: "Payments", + newName: "FK_InvoiceId"); + + migrationBuilder.RenameIndex( + name: "IX_Payments_FK_StoreId", + table: "Payments", + newName: "IX_Payments_FK_InvoiceId"); + + migrationBuilder.RenameColumn( + name: "ReceiptConfirmedBy", + table: "LoadingSheets", + newName: "ConfirmedBy"); + + migrationBuilder.RenameColumn( + name: "ReceiptConfirmedAt", + table: "LoadingSheets", + newName: "ConfirmedAt"); + + migrationBuilder.RenameColumn( + name: "FK_SourceWarehouseId", + table: "LoadingSheets", + newName: "PopulatedBy"); + + migrationBuilder.RenameColumn( + name: "FK_OrderId", + table: "DeliveryTasks", + newName: "FK_ShopPOId"); + + migrationBuilder.RenameIndex( + name: "IX_DeliveryTasks_FK_OrderId", + table: "DeliveryTasks", + newName: "IX_DeliveryTasks_FK_ShopPOId"); + + migrationBuilder.AddColumn( + name: "PopulatedAt", + table: "LoadingSheets", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "CreatedAt", + table: "LoadingSheetItems", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "FK_ShopPOItemId", + table: "LoadingSheetItems", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "FK_WarehouseId", + table: "LoadingSheetItems", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "IsActive", + table: "LoadingSheetItems", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.CreateTable( + name: "ShopPOs", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_StoreId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + RaisedById = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + InvoiceId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false), + Status = table.Column(type: "int", nullable: false), + ConfirmedAt = table.Column(type: "datetime(6)", nullable: true), + ConfirmedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + FulfilledAt = table.Column(type: "datetime(6)", nullable: true), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ShopPOs", x => x.Id); + table.ForeignKey( + name: "FK_ShopPOs_Stores_FK_StoreId", + column: x => x.FK_StoreId, + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Invoices", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ShopPOId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Status = table.Column(type: "int", nullable: false), + PaymentStatus = table.Column(type: "int", nullable: false), + CreatedBy = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + PrintedAt = table.Column(type: "datetime(6)", nullable: true), + PrintedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + FinalizedAt = table.Column(type: "datetime(6)", nullable: true), + FinalizedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Invoices", x => x.Id); + table.ForeignKey( + name: "FK_Invoices_ShopPOs_FK_ShopPOId", + column: x => x.FK_ShopPOId, + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "LoadingSheetOrders", + columns: table => new + { + FK_LoadingSheetId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ShopPOId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_LoadingSheetOrders", x => new { x.FK_LoadingSheetId, x.FK_ShopPOId }); + table.ForeignKey( + name: "FK_LoadingSheetOrders_LoadingSheets_FK_LoadingSheetId", + column: x => x.FK_LoadingSheetId, + principalTable: "LoadingSheets", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_LoadingSheetOrders_ShopPOs_FK_ShopPOId", + column: x => x.FK_ShopPOId, + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ShopPOItems", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ShopPOId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ItemId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Quantity = table.Column(type: "int", nullable: false), + QuantityFulfilled = table.Column(type: "int", nullable: false), + UnitPrice = table.Column(type: "decimal(65,30)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ShopPOItems", x => x.Id); + table.ForeignKey( + name: "FK_ShopPOItems_Items_FK_ItemId", + column: x => x.FK_ItemId, + principalTable: "Items", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_ShopPOItems_ShopPOs_FK_ShopPOId", + column: x => x.FK_ShopPOId, + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000001"), + column: "Status", + value: 2); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000002"), + column: "Status", + value: 0); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000001"), + columns: new[] { "CreatedAt", "FK_ShopPOItemId", "FK_WarehouseId", "IsActive" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), null, new Guid("27000000-0000-0000-0000-000000000001"), true }); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000002"), + columns: new[] { "CreatedAt", "FK_ShopPOItemId", "FK_WarehouseId", "IsActive" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), null, new Guid("27000000-0000-0000-0000-000000000001"), true }); + + migrationBuilder.UpdateData( + table: "LoadingSheets", + keyColumn: "Id", + keyValue: new Guid("35000000-0000-0000-0000-000000000001"), + columns: new[] { "ConfirmedAt", "ConfirmedBy", "PopulatedAt", "PopulatedBy", "Status" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), 1 }); + + migrationBuilder.UpdateData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000001"), + column: "FK_InvoiceId", + value: new Guid("34500000-0000-0000-0000-000000000001")); + + migrationBuilder.InsertData( + table: "ShopPOs", + columns: new[] { "Id", "ConfirmedAt", "ConfirmedBy", "CreatedAt", "FK_StoreId", "FulfilledAt", "InvoiceId", "IsActive", "RaisedById", "Status", "TotalAmount" }, + values: new object[,] + { + { new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("26000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34500000-0000-0000-0000-000000000001"), true, new Guid("29000000-0000-0000-0000-000000000002"), 2, 3000m }, + { new Guid("33000000-0000-0000-0000-000000000002"), null, null, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("26000000-0000-0000-0000-000000000005"), null, null, true, new Guid("29000000-0000-0000-0000-000000000003"), 0, 1200m } + }); + + migrationBuilder.InsertData( + table: "Invoices", + columns: new[] { "Id", "CreatedAt", "CreatedBy", "FK_ShopPOId", "FinalizedAt", "FinalizedBy", "IsActive", "PaymentStatus", "PrintedAt", "PrintedBy", "Status", "TotalAmount" }, + values: new object[] { new Guid("34500000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), true, 2, new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000002"), 2, 3000m }); + + migrationBuilder.InsertData( + table: "ShopPOItems", + columns: new[] { "Id", "CreatedAt", "FK_ItemId", "FK_ShopPOId", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" }, + values: new object[,] + { + { new Guid("34000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000001"), new Guid("33000000-0000-0000-0000-000000000001"), true, 30, 30, 60m }, + { new Guid("34000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000001"), true, 24, 24, 50m }, + { new Guid("34000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000002"), true, 10, 0, 120m } + }); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheetItems_FK_ShopPOItemId", + table: "LoadingSheetItems", + column: "FK_ShopPOItemId"); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheetItems_FK_WarehouseId", + table: "LoadingSheetItems", + column: "FK_WarehouseId"); + + migrationBuilder.CreateIndex( + name: "IX_Invoices_FK_ShopPOId", + table: "Invoices", + column: "FK_ShopPOId"); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheetOrders_FK_ShopPOId", + table: "LoadingSheetOrders", + column: "FK_ShopPOId"); + + migrationBuilder.CreateIndex( + name: "IX_ShopPOItems_FK_ItemId", + table: "ShopPOItems", + column: "FK_ItemId"); + + migrationBuilder.CreateIndex( + name: "IX_ShopPOItems_FK_ShopPOId", + table: "ShopPOItems", + column: "FK_ShopPOId"); + + migrationBuilder.CreateIndex( + name: "IX_ShopPOs_FK_StoreId", + table: "ShopPOs", + column: "FK_StoreId"); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryTasks_ShopPOs_FK_ShopPOId", + table: "DeliveryTasks", + column: "FK_ShopPOId", + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", + table: "LoadingSheetItems", + column: "FK_LoadingSheetId", + principalTable: "LoadingSheets", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_ShopPOItems_FK_ShopPOItemId", + table: "LoadingSheetItems", + column: "FK_ShopPOItemId", + principalTable: "ShopPOItems", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_Warehouses_FK_WarehouseId", + table: "LoadingSheetItems", + column: "FK_WarehouseId", + principalTable: "Warehouses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_Payments_Invoices_FK_InvoiceId", + table: "Payments", + column: "FK_InvoiceId", + principalTable: "Invoices", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_SaleReturns_ShopPOs_FK_ShopPOId", + table: "SaleReturns", + column: "FK_ShopPOId", + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_SchemeRedemptions_ShopPOs_FK_ShopPOId", + table: "SchemeRedemptions", + column: "FK_ShopPOId", + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_DeliveryTasks_ShopPOs_FK_ShopPOId", + table: "DeliveryTasks"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", + table: "LoadingSheetItems"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheetItems_ShopPOItems_FK_ShopPOItemId", + table: "LoadingSheetItems"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheetItems_Warehouses_FK_WarehouseId", + table: "LoadingSheetItems"); + + migrationBuilder.DropForeignKey( + name: "FK_Payments_Invoices_FK_InvoiceId", + table: "Payments"); + + migrationBuilder.DropForeignKey( + name: "FK_SaleReturns_ShopPOs_FK_ShopPOId", + table: "SaleReturns"); + + migrationBuilder.DropForeignKey( + name: "FK_SchemeRedemptions_ShopPOs_FK_ShopPOId", + table: "SchemeRedemptions"); + + migrationBuilder.DropTable( + name: "Invoices"); + + migrationBuilder.DropTable( + name: "LoadingSheetOrders"); + + migrationBuilder.DropTable( + name: "ShopPOItems"); + + migrationBuilder.DropTable( + name: "ShopPOs"); + + migrationBuilder.DropIndex( + name: "IX_LoadingSheetItems_FK_ShopPOItemId", + table: "LoadingSheetItems"); + + migrationBuilder.DropIndex( + name: "IX_LoadingSheetItems_FK_WarehouseId", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "PopulatedAt", + table: "LoadingSheets"); + + migrationBuilder.DropColumn( + name: "CreatedAt", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "FK_ShopPOItemId", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "FK_WarehouseId", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "IsActive", + table: "LoadingSheetItems"); + + migrationBuilder.RenameColumn( + name: "FK_ShopPOId", + table: "SchemeRedemptions", + newName: "FK_OrderId"); + + migrationBuilder.RenameIndex( + name: "IX_SchemeRedemptions_FK_ShopPOId", + table: "SchemeRedemptions", + newName: "IX_SchemeRedemptions_FK_OrderId"); + + migrationBuilder.RenameColumn( + name: "FK_ShopPOId", + table: "SaleReturns", + newName: "FK_OrderId"); + + migrationBuilder.RenameIndex( + name: "IX_SaleReturns_FK_ShopPOId", + table: "SaleReturns", + newName: "IX_SaleReturns_FK_OrderId"); + + migrationBuilder.RenameColumn( + name: "FK_InvoiceId", + table: "Payments", + newName: "FK_StoreId"); + + migrationBuilder.RenameIndex( + name: "IX_Payments_FK_InvoiceId", + table: "Payments", + newName: "IX_Payments_FK_StoreId"); + + migrationBuilder.RenameColumn( + name: "PopulatedBy", + table: "LoadingSheets", + newName: "FK_SourceWarehouseId"); + + migrationBuilder.RenameColumn( + name: "ConfirmedBy", + table: "LoadingSheets", + newName: "ReceiptConfirmedBy"); + + migrationBuilder.RenameColumn( + name: "ConfirmedAt", + table: "LoadingSheets", + newName: "ReceiptConfirmedAt"); + + migrationBuilder.RenameColumn( + name: "FK_ShopPOId", + table: "DeliveryTasks", + newName: "FK_OrderId"); + + migrationBuilder.RenameIndex( + name: "IX_DeliveryTasks_FK_ShopPOId", + table: "DeliveryTasks", + newName: "IX_DeliveryTasks_FK_OrderId"); + + migrationBuilder.AddColumn( + name: "FK_SaleId", + table: "Payments", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "DispatchConfirmedAt", + table: "LoadingSheets", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "DispatchConfirmedBy", + table: "LoadingSheets", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "QuantityReceived", + table: "LoadingSheetItems", + type: "decimal(65,30)", + nullable: true); + + migrationBuilder.AddColumn( + name: "QuantityResolved", + table: "LoadingSheetItems", + type: "decimal(65,30)", + nullable: true); + + migrationBuilder.AddColumn( + name: "ActivatedAt", + table: "DeliveryRuns", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "FK_RouteId", + table: "DeliveryRuns", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "FK_SourceWarehouseId", + table: "DeliveryRuns", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "RideType", + table: "DeliveryRuns", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateTable( + name: "Sales", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedByUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_RideId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + FK_StoreId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CompletedAt = table.Column(type: "datetime(6)", nullable: true), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + FulfillImmediately = table.Column(type: "tinyint(1)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + PaymentStatus = table.Column(type: "int", nullable: false), + SaleDate = table.Column(type: "datetime(6)", nullable: false), + Status = table.Column(type: "int", nullable: false), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Sales", x => x.Id); + table.ForeignKey( + name: "FK_Sales_DeliveryRuns_FK_RideId", + column: x => x.FK_RideId, + principalTable: "DeliveryRuns", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Sales_Stores_FK_StoreId", + column: x => x.FK_StoreId, + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Sales_Users_CreatedByUserId", + column: x => x.CreatedByUserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Orders", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_SaleId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_StoreId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + FulfilledAt = table.Column(type: "datetime(6)", nullable: true), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + OrderDate = table.Column(type: "datetime(6)", nullable: false), + Status = table.Column(type: "int", nullable: false), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_Sales_FK_SaleId", + column: x => x.FK_SaleId, + principalTable: "Sales", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Orders_Stores_FK_StoreId", + column: x => x.FK_StoreId, + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "OrderItems", + columns: table => new + { + FK_OrderId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ItemId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + Quantity = table.Column(type: "int", nullable: false), + QuantityFulfilled = table.Column(type: "int", nullable: false), + UnitPrice = table.Column(type: "decimal(65,30)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OrderItems", x => new { x.FK_OrderId, x.FK_ItemId }); + table.ForeignKey( + name: "FK_OrderItems_Items_FK_ItemId", + column: x => x.FK_ItemId, + principalTable: "Items", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_OrderItems_Orders_FK_OrderId", + column: x => x.FK_OrderId, + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000001"), + columns: new[] { "ActivatedAt", "FK_RouteId", "FK_SourceWarehouseId", "RideType", "Status" }, + values: new object[] { new DateTime(2026, 8, 25, 8, 15, 0, 0, DateTimeKind.Unspecified), new Guid("25000000-0000-0000-0000-000000000001"), new Guid("27000000-0000-0000-0000-000000000001"), 1, 5 }); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000002"), + columns: new[] { "ActivatedAt", "FK_RouteId", "FK_SourceWarehouseId", "RideType", "Status" }, + values: new object[] { new DateTime(2026, 8, 30, 9, 20, 0, 0, DateTimeKind.Unspecified), new Guid("25000000-0000-0000-0000-000000000003"), new Guid("27000000-0000-0000-0000-000000000002"), 0, 2 }); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000001"), + columns: new[] { "QuantityReceived", "QuantityResolved" }, + values: new object[] { 50m, null }); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000002"), + columns: new[] { "QuantityReceived", "QuantityResolved" }, + values: new object[] { 30m, null }); + + migrationBuilder.UpdateData( + table: "LoadingSheets", + keyColumn: "Id", + keyValue: new Guid("35000000-0000-0000-0000-000000000001"), + columns: new[] { "DispatchConfirmedAt", "DispatchConfirmedBy", "FK_SourceWarehouseId", "ReceiptConfirmedAt", "ReceiptConfirmedBy", "Status" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new Guid("27000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 14, 5, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000004"), 2 }); + + migrationBuilder.UpdateData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000001"), + columns: new[] { "FK_SaleId", "FK_StoreId" }, + values: new object[] { new Guid("32000000-0000-0000-0000-000000000001"), new Guid("26000000-0000-0000-0000-000000000001") }); + + migrationBuilder.InsertData( + table: "Sales", + columns: new[] { "Id", "CompletedAt", "CreatedAt", "CreatedByUserId", "FK_RideId", "FK_StoreId", "FulfillImmediately", "IsActive", "PaymentStatus", "SaleDate", "Status", "TotalAmount" }, + values: new object[,] + { + { new Guid("32000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000002"), new Guid("31000000-0000-0000-0000-000000000001"), new Guid("26000000-0000-0000-0000-000000000001"), false, true, 2, new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), 1, 3000m }, + { new Guid("32000000-0000-0000-0000-000000000002"), null, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new Guid("31000000-0000-0000-0000-000000000002"), new Guid("26000000-0000-0000-0000-000000000005"), false, true, 0, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), 0, 1200m } + }); + + migrationBuilder.InsertData( + table: "Orders", + columns: new[] { "Id", "CreatedAt", "FK_SaleId", "FK_StoreId", "FulfilledAt", "IsActive", "OrderDate", "Status", "TotalAmount" }, + values: new object[,] + { + { new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("32000000-0000-0000-0000-000000000001"), new Guid("26000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), true, new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), 2, 3000m }, + { new Guid("33000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("32000000-0000-0000-0000-000000000002"), new Guid("26000000-0000-0000-0000-000000000005"), null, true, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), 0, 1200m } + }); + + migrationBuilder.InsertData( + table: "OrderItems", + columns: new[] { "FK_ItemId", "FK_OrderId", "CreatedAt", "Id", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" }, + values: new object[,] + { + { new Guid("23000000-0000-0000-0000-000000000001"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000001"), true, 30, 30, 60m }, + { new Guid("23000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000002"), true, 24, 24, 50m }, + { new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000003"), true, 10, 0, 120m } + }); + + migrationBuilder.CreateIndex( + name: "IX_Payments_FK_SaleId", + table: "Payments", + column: "FK_SaleId"); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheets_FK_SourceWarehouseId", + table: "LoadingSheets", + column: "FK_SourceWarehouseId"); + + migrationBuilder.CreateIndex( + name: "IX_DeliveryRuns_FK_RouteId", + table: "DeliveryRuns", + column: "FK_RouteId"); + + migrationBuilder.CreateIndex( + name: "IX_DeliveryRuns_FK_SourceWarehouseId", + table: "DeliveryRuns", + column: "FK_SourceWarehouseId"); + + migrationBuilder.CreateIndex( + name: "IX_OrderItems_FK_ItemId", + table: "OrderItems", + column: "FK_ItemId"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_FK_SaleId", + table: "Orders", + column: "FK_SaleId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Orders_FK_StoreId", + table: "Orders", + column: "FK_StoreId"); + + migrationBuilder.CreateIndex( + name: "IX_Sales_CreatedByUserId", + table: "Sales", + column: "CreatedByUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Sales_FK_RideId", + table: "Sales", + column: "FK_RideId"); + + migrationBuilder.CreateIndex( + name: "IX_Sales_FK_StoreId", + table: "Sales", + column: "FK_StoreId"); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryRuns_Routes_FK_RouteId", + table: "DeliveryRuns", + column: "FK_RouteId", + principalTable: "Routes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId", + table: "DeliveryRuns", + column: "FK_SourceWarehouseId", + principalTable: "Warehouses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryTasks_Orders_FK_OrderId", + table: "DeliveryTasks", + column: "FK_OrderId", + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", + table: "LoadingSheetItems", + column: "FK_LoadingSheetId", + principalTable: "LoadingSheets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheets_Warehouses_FK_SourceWarehouseId", + table: "LoadingSheets", + column: "FK_SourceWarehouseId", + principalTable: "Warehouses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_Payments_Sales_FK_SaleId", + table: "Payments", + column: "FK_SaleId", + principalTable: "Sales", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Payments_Stores_FK_StoreId", + table: "Payments", + column: "FK_StoreId", + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_SaleReturns_Orders_FK_OrderId", + table: "SaleReturns", + column: "FK_OrderId", + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_SchemeRedemptions_Orders_FK_OrderId", + table: "SchemeRedemptions", + column: "FK_OrderId", + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + + private static void DropForeignKeyIfExists(MigrationBuilder migrationBuilder, string tableName, string constraintName) + { + migrationBuilder.Sql($"ALTER TABLE `{tableName}` DROP FOREIGN KEY IF EXISTS `{constraintName}`;"); + } + + private static void DropIndexIfExists(MigrationBuilder migrationBuilder, string tableName, string indexName) + { + migrationBuilder.Sql($""" + SET @sql = IF( + EXISTS( + SELECT 1 + FROM INFORMATION_SCHEMA.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = '{tableName}' + AND INDEX_NAME = '{indexName}' + ), + 'DROP INDEX `{indexName}` ON `{tableName}`', + 'SELECT 1' + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + """); + } + + private static void DropColumnIfExists(MigrationBuilder migrationBuilder, string tableName, string columnName) + { + migrationBuilder.Sql($""" + SET @sql = IF( + EXISTS( + SELECT 1 + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = '{tableName}' + AND COLUMN_NAME = '{columnName}' + ), + 'ALTER TABLE `{tableName}` DROP COLUMN `{columnName}`', + 'SELECT 1' + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + """); + } + } +} diff --git a/Distribution/Migrations/20260917042658_AddSysConfig.Designer.cs b/Distribution/Migrations/20260917042658_AddSysConfig.Designer.cs new file mode 100644 index 0000000..8470a58 --- /dev/null +++ b/Distribution/Migrations/20260917042658_AddSysConfig.Designer.cs @@ -0,0 +1,4055 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917042658_AddSysConfig")] + partial class AddSysConfig + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedAt") + .HasColumnType("datetime(6)"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RequestedAt") + .HasColumnType("datetime(6)"); + + b.Property("RequestedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TypeCode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("RideCancelRequests"); + + b.HasData( + new + { + Id = new Guid("65000000-0000-0000-0000-000000000001"), + ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), + ApprovedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + Reason = "Reported minor engine issue, resolved after inspection", + RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), + RequestedBy = new Guid("29000000-0000-0000-0000-000000000005"), + Status = 2, + TypeCode = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917042658_AddSysConfig.cs b/Distribution/Migrations/20260917042658_AddSysConfig.cs new file mode 100644 index 0000000..b566652 --- /dev/null +++ b/Distribution/Migrations/20260917042658_AddSysConfig.cs @@ -0,0 +1,44 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Distribution.Migrations +{ + /// + public partial class AddSysConfig : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "SysConfigs", + columns: table => new + { + Key = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false), + UpdatedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_SysConfigs", x => x.Key); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.InsertData( + table: "SysConfigs", + columns: new[] { "Key", "UpdatedAt", "UpdatedBy", "Value" }, + values: new object[] { "InvoiceCreationMode", new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), null, "ModeB" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SysConfigs"); + } + } +} diff --git a/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.Designer.cs b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.Designer.cs new file mode 100644 index 0000000..6d83405 --- /dev/null +++ b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.Designer.cs @@ -0,0 +1,3992 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917090213_RemoveRideCancelRequest")] + partial class RemoveRideCancelRequest + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.cs b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.cs new file mode 100644 index 0000000..54a5100 --- /dev/null +++ b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.cs @@ -0,0 +1,59 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Distribution.Migrations +{ + /// + public partial class RemoveRideCancelRequest : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RideCancelRequests"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "RideCancelRequests", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_RideId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ApprovedAt = table.Column(type: "datetime(6)", nullable: true), + ApprovedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Reason = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + RequestedAt = table.Column(type: "datetime(6)", nullable: false), + RequestedBy = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Status = table.Column(type: "int", nullable: false), + TypeCode = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RideCancelRequests", x => x.Id); + table.ForeignKey( + name: "FK_RideCancelRequests_DeliveryRuns_FK_RideId", + column: x => x.FK_RideId, + principalTable: "DeliveryRuns", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.InsertData( + table: "RideCancelRequests", + columns: new[] { "Id", "ApprovedAt", "ApprovedBy", "FK_RideId", "Reason", "RequestedAt", "RequestedBy", "Status", "TypeCode" }, + values: new object[] { new Guid("65000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new Guid("31000000-0000-0000-0000-000000000002"), "Reported minor engine issue, resolved after inspection", new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000005"), 2, 0 }); + + migrationBuilder.CreateIndex( + name: "IX_RideCancelRequests_FK_RideId", + table: "RideCancelRequests", + column: "FK_RideId"); + } + } +} diff --git a/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.Designer.cs b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.Designer.cs new file mode 100644 index 0000000..6427823 --- /dev/null +++ b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.Designer.cs @@ -0,0 +1,4005 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917094455_AddPaymentChequeAndEntryMode")] + partial class AddPaymentChequeAndEntryMode + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("ChequeDate") + .HasColumnType("datetime(6)"); + + b.Property("ChequeNumber") + .HasColumnType("longtext"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EntryMode") + .HasColumnType("int"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.Property("RecordedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.cs b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.cs new file mode 100644 index 0000000..618dd61 --- /dev/null +++ b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.cs @@ -0,0 +1,69 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Distribution.Migrations +{ + /// + public partial class AddPaymentChequeAndEntryMode : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ChequeDate", + table: "Payments", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "ChequeNumber", + table: "Payments", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "EntryMode", + table: "Payments", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "RecordedBy", + table: "Payments", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.UpdateData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000001"), + columns: new[] { "ChequeDate", "ChequeNumber", "EntryMode", "RecordedBy" }, + values: new object[] { null, null, 0, null }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ChequeDate", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "ChequeNumber", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "EntryMode", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "RecordedBy", + table: "Payments"); + } + } +} diff --git a/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.Designer.cs b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.Designer.cs new file mode 100644 index 0000000..2fd6275 --- /dev/null +++ b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.Designer.cs @@ -0,0 +1,4082 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917104905_SeedInvoice2AndMorePayments")] + partial class SeedInvoice2AndMorePayments + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("34500000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + PaymentStatus = 1, + PrintedAt = new DateTime(2026, 8, 31, 9, 15, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 1, + TotalAmount = 2400m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("ChequeDate") + .HasColumnType("datetime(6)"); + + b.Property("ChequeNumber") + .HasColumnType("longtext"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EntryMode") + .HasColumnType("int"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.Property("RecordedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000002"), + Amount = 1000m, + CollectedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000003"), + Amount = 800m, + ChequeDate = new DateTime(2026, 8, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + ChequeNumber = "000456", + CollectedAt = new DateTime(2026, 8, 31, 11, 0, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 18, 0, 0, 0, DateTimeKind.Unspecified), + EntryMode = 1, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 1, + RecordedBy = new Guid("29000000-0000-0000-0000-000000000001") + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000004"), + Amount = 300m, + CollectedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000003"), + ConfirmedAt = new DateTime(2026, 8, 31, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + FulfilledAt = new DateTime(2026, 8, 31, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 2, + TotalAmount = 2400m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + Quantity = 20, + QuantityFulfilled = 20, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.cs b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.cs new file mode 100644 index 0000000..30be6b0 --- /dev/null +++ b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.cs @@ -0,0 +1,76 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Distribution.Migrations +{ + /// + public partial class SeedInvoice2AndMorePayments : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "ShopPOs", + columns: new[] { "Id", "ConfirmedAt", "ConfirmedBy", "CreatedAt", "FK_StoreId", "FulfilledAt", "InvoiceId", "IsActive", "RaisedById", "Status", "TotalAmount" }, + values: new object[] { new Guid("33000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 8, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("26000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 31, 13, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34500000-0000-0000-0000-000000000002"), true, new Guid("29000000-0000-0000-0000-000000000003"), 2, 2400m }); + + migrationBuilder.InsertData( + table: "Invoices", + columns: new[] { "Id", "CreatedAt", "CreatedBy", "FK_ShopPOId", "FinalizedAt", "FinalizedBy", "IsActive", "PaymentStatus", "PrintedAt", "PrintedBy", "Status", "TotalAmount" }, + values: new object[] { new Guid("34500000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000003"), null, null, true, 1, new DateTime(2026, 8, 31, 9, 15, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), 1, 2400m }); + + migrationBuilder.InsertData( + table: "ShopPOItems", + columns: new[] { "Id", "CreatedAt", "FK_ItemId", "FK_ShopPOId", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" }, + values: new object[] { new Guid("34000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000003"), true, 20, 20, 120m }); + + migrationBuilder.InsertData( + table: "Payments", + columns: new[] { "Id", "Amount", "ChequeDate", "ChequeNumber", "CollectedAt", "CollectedBy", "CreatedAt", "EntryMode", "FK_InvoiceId", "IsActive", "Method", "RecordedBy" }, + values: new object[,] + { + { new Guid("47000000-0000-0000-0000-000000000002"), 1000m, null, null, new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), 0, new Guid("34500000-0000-0000-0000-000000000002"), true, 0, null }, + { new Guid("47000000-0000-0000-0000-000000000003"), 800m, new DateTime(2026, 8, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), "000456", new DateTime(2026, 8, 31, 11, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 18, 0, 0, 0, DateTimeKind.Unspecified), 1, new Guid("34500000-0000-0000-0000-000000000002"), true, 1, new Guid("29000000-0000-0000-0000-000000000001") }, + { new Guid("47000000-0000-0000-0000-000000000004"), 300m, null, null, new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), 0, new Guid("34500000-0000-0000-0000-000000000002"), true, 2, null } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000002")); + + migrationBuilder.DeleteData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000003")); + + migrationBuilder.DeleteData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000004")); + + migrationBuilder.DeleteData( + table: "ShopPOItems", + keyColumn: "Id", + keyValue: new Guid("34000000-0000-0000-0000-000000000004")); + + migrationBuilder.DeleteData( + table: "Invoices", + keyColumn: "Id", + keyValue: new Guid("34500000-0000-0000-0000-000000000002")); + + migrationBuilder.DeleteData( + table: "ShopPOs", + keyColumn: "Id", + keyValue: new Guid("33000000-0000-0000-0000-000000000003")); + } + } +} diff --git a/Distribution/Migrations/AppDBContextModelSnapshot.cs b/Distribution/Migrations/AppDBContextModelSnapshot.cs index 53c706b..8f517d0 100644 --- a/Distribution/Migrations/AppDBContextModelSnapshot.cs +++ b/Distribution/Migrations/AppDBContextModelSnapshot.cs @@ -206,9 +206,6 @@ namespace Distribution.Migrations .ValueGeneratedOnAdd() .HasColumnType("char(36)"); - b.Property("ActivatedAt") - .HasColumnType("datetime(6)"); - b.Property("ClosedAt") .HasColumnType("datetime(6)"); @@ -218,12 +215,6 @@ namespace Distribution.Migrations b.Property("FK_DriverProfileId") .HasColumnType("char(36)"); - b.Property("FK_RouteId") - .HasColumnType("char(36)"); - - b.Property("FK_SourceWarehouseId") - .HasColumnType("char(36)"); - b.Property("FK_VehicleId") .HasColumnType("char(36)"); @@ -236,9 +227,6 @@ namespace Distribution.Migrations b.Property("Meterstart") .HasColumnType("int"); - b.Property("RideType") - .HasColumnType("int"); - b.Property("StartedAt") .HasColumnType("datetime(6)"); @@ -249,10 +237,6 @@ namespace Distribution.Migrations b.HasIndex("FK_DriverProfileId"); - b.HasIndex("FK_RouteId"); - - b.HasIndex("FK_SourceWarehouseId"); - b.HasIndex("FK_VehicleId"); b.ToTable("DeliveryRuns"); @@ -261,35 +245,27 @@ namespace Distribution.Migrations new { Id = new Guid("31000000-0000-0000-0000-000000000001"), - ActivatedAt = new DateTime(2026, 8, 25, 8, 15, 0, 0, DateTimeKind.Unspecified), ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), - FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), - FK_SourceWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), IsActive = true, Meterend = 10550, Meterstart = 10500, - RideType = 1, StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), - Status = 5 + Status = 2 }, new { Id = new Guid("31000000-0000-0000-0000-000000000002"), - ActivatedAt = new DateTime(2026, 8, 30, 9, 20, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), - FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), - FK_SourceWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), IsActive = true, Meterend = 0, Meterstart = 20300, - RideType = 0, StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), - Status = 2 + Status = 0 }); }); @@ -308,10 +284,10 @@ namespace Distribution.Migrations b.Property("CustomerConfirmed") .HasColumnType("tinyint(1)"); - b.Property("FK_OrderId") + b.Property("FK_RideId") .HasColumnType("char(36)"); - b.Property("FK_RideId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); b.Property("IsActive") @@ -328,10 +304,10 @@ namespace Distribution.Migrations b.HasKey("Id"); - b.HasIndex("FK_OrderId"); - b.HasIndex("FK_RideId"); + b.HasIndex("FK_ShopPOId"); + b.ToTable("DeliveryTasks"); b.HasData( @@ -340,8 +316,8 @@ namespace Distribution.Migrations Id = new Guid("37000000-0000-0000-0000-000000000001"), CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), CustomerConfirmed = false, - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000002"), FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), IsActive = true, Sequence = 1, Status = 0 @@ -536,6 +512,82 @@ namespace Distribution.Migrations }); }); + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("34500000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + PaymentStatus = 1, + PrintedAt = new DateTime(2026, 8, 31, 9, 15, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 1, + TotalAmount = 2400m + }); + }); + modelBuilder.Entity("Distribution.Models.Item", b => { b.Property("Id") @@ -663,28 +715,25 @@ namespace Distribution.Migrations .ValueGeneratedOnAdd() .HasColumnType("char(36)"); + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + b.Property("CreatedAt") .HasColumnType("datetime(6)"); - b.Property("DispatchConfirmedAt") - .HasColumnType("datetime(6)"); - - b.Property("DispatchConfirmedBy") - .HasColumnType("char(36)"); - b.Property("FK_RideId") .HasColumnType("char(36)"); - b.Property("FK_SourceWarehouseId") - .HasColumnType("char(36)"); - b.Property("IsActive") .HasColumnType("tinyint(1)"); - b.Property("ReceiptConfirmedAt") + b.Property("PopulatedAt") .HasColumnType("datetime(6)"); - b.Property("ReceiptConfirmedBy") + b.Property("PopulatedBy") .HasColumnType("char(36)"); b.Property("Status") @@ -694,23 +743,20 @@ namespace Distribution.Migrations b.HasIndex("FK_RideId"); - b.HasIndex("FK_SourceWarehouseId"); - b.ToTable("LoadingSheets"); b.HasData( new { Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), - DispatchConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), - DispatchConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), - FK_SourceWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), IsActive = true, - ReceiptConfirmedAt = new DateTime(2026, 8, 25, 14, 5, 0, 0, DateTimeKind.Unspecified), - ReceiptConfirmedBy = new Guid("29000000-0000-0000-0000-000000000004"), - Status = 2 + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 }); }); @@ -720,179 +766,75 @@ namespace Distribution.Migrations .ValueGeneratedOnAdd() .HasColumnType("char(36)"); + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + b.Property("FK_ItemId") .HasColumnType("char(36)"); b.Property("FK_LoadingSheetId") .HasColumnType("char(36)"); + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + b.Property("QuantityDispatched") .HasColumnType("decimal(65,30)"); - b.Property("QuantityReceived") - .HasColumnType("decimal(65,30)"); - - b.Property("QuantityResolved") - .HasColumnType("decimal(65,30)"); - b.HasKey("Id"); b.HasIndex("FK_ItemId"); b.HasIndex("FK_LoadingSheetId"); + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + b.ToTable("LoadingSheetItems"); b.HasData( new { Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), - QuantityDispatched = 50m, - QuantityReceived = 50m + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m }, new { Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), - QuantityDispatched = 30m, - QuantityReceived = 30m + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m }); }); - modelBuilder.Entity("Distribution.Models.Order", b => + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => { - b.Property("Id") - .ValueGeneratedOnAdd() + b.Property("FK_LoadingSheetId") .HasColumnType("char(36)"); - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("FK_SaleId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); - b.Property("FK_StoreId") - .HasColumnType("char(36)"); + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); - b.Property("FulfilledAt") - .HasColumnType("datetime(6)"); + b.HasIndex("FK_ShopPOId"); - b.Property("IsActive") - .HasColumnType("tinyint(1)"); - - b.Property("OrderDate") - .HasColumnType("datetime(6)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TotalAmount") - .HasColumnType("decimal(65,30)"); - - b.HasKey("Id"); - - b.HasIndex("FK_SaleId") - .IsUnique(); - - b.HasIndex("FK_StoreId"); - - b.ToTable("Orders"); - - b.HasData( - new - { - Id = new Guid("33000000-0000-0000-0000-000000000001"), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - FK_SaleId = new Guid("32000000-0000-0000-0000-000000000001"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), - FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), - IsActive = true, - OrderDate = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Status = 2, - TotalAmount = 3000m - }, - new - { - Id = new Guid("33000000-0000-0000-0000-000000000002"), - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - FK_SaleId = new Guid("32000000-0000-0000-0000-000000000002"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), - IsActive = true, - OrderDate = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - Status = 0, - TotalAmount = 1200m - }); - }); - - modelBuilder.Entity("Distribution.Models.OrderItem", b => - { - b.Property("FK_OrderId") - .HasColumnType("char(36)"); - - b.Property("FK_ItemId") - .HasColumnType("char(36)"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Id") - .HasColumnType("char(36)"); - - b.Property("IsActive") - .HasColumnType("tinyint(1)"); - - b.Property("Quantity") - .HasColumnType("int"); - - b.Property("QuantityFulfilled") - .HasColumnType("int"); - - b.Property("UnitPrice") - .HasColumnType("decimal(65,30)"); - - b.HasKey("FK_OrderId", "FK_ItemId"); - - b.HasIndex("FK_ItemId"); - - b.ToTable("OrderItems"); - - b.HasData( - new - { - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), - FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Id = new Guid("34000000-0000-0000-0000-000000000001"), - IsActive = true, - Quantity = 30, - QuantityFulfilled = 30, - UnitPrice = 60m - }, - new - { - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), - FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Id = new Guid("34000000-0000-0000-0000-000000000002"), - IsActive = true, - Quantity = 24, - QuantityFulfilled = 24, - UnitPrice = 50m - }, - new - { - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000002"), - FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - Id = new Guid("34000000-0000-0000-0000-000000000003"), - IsActive = true, - Quantity = 10, - QuantityFulfilled = 0, - UnitPrice = 120m - }); + b.ToTable("LoadingSheetOrders"); }); modelBuilder.Entity("Distribution.Models.Payment", b => @@ -904,6 +846,12 @@ namespace Distribution.Migrations b.Property("Amount") .HasColumnType("decimal(65,30)"); + b.Property("ChequeDate") + .HasColumnType("datetime(6)"); + + b.Property("ChequeNumber") + .HasColumnType("longtext"); + b.Property("CollectedAt") .HasColumnType("datetime(6)"); @@ -913,10 +861,10 @@ namespace Distribution.Migrations b.Property("CreatedAt") .HasColumnType("datetime(6)"); - b.Property("FK_SaleId") - .HasColumnType("char(36)"); + b.Property("EntryMode") + .HasColumnType("int"); - b.Property("FK_StoreId") + b.Property("FK_InvoiceId") .HasColumnType("char(36)"); b.Property("IsActive") @@ -925,11 +873,12 @@ namespace Distribution.Migrations b.Property("Method") .HasColumnType("int"); + b.Property("RecordedBy") + .HasColumnType("char(36)"); + b.HasKey("Id"); - b.HasIndex("FK_SaleId"); - - b.HasIndex("FK_StoreId"); + b.HasIndex("FK_InvoiceId"); b.ToTable("Payments"); @@ -941,10 +890,49 @@ namespace Distribution.Migrations CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), - FK_SaleId = new Guid("32000000-0000-0000-0000-000000000001"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), IsActive = true, Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000002"), + Amount = 1000m, + CollectedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000003"), + Amount = 800m, + ChequeDate = new DateTime(2026, 8, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + ChequeNumber = "000456", + CollectedAt = new DateTime(2026, 8, 31, 11, 0, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 18, 0, 0, 0, DateTimeKind.Unspecified), + EntryMode = 1, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 1, + RecordedBy = new Guid("29000000-0000-0000-0000-000000000001") + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000004"), + Amount = 300m, + CollectedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 2 }); }); @@ -1484,58 +1472,6 @@ namespace Distribution.Migrations }); }); - modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("char(36)"); - - b.Property("ApprovedAt") - .HasColumnType("datetime(6)"); - - b.Property("ApprovedBy") - .HasColumnType("char(36)"); - - b.Property("FK_RideId") - .HasColumnType("char(36)"); - - b.Property("Reason") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RequestedAt") - .HasColumnType("datetime(6)"); - - b.Property("RequestedBy") - .HasColumnType("char(36)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TypeCode") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("FK_RideId"); - - b.ToTable("RideCancelRequests"); - - b.HasData( - new - { - Id = new Guid("65000000-0000-0000-0000-000000000001"), - ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), - ApprovedBy = new Guid("29000000-0000-0000-0000-000000000001"), - FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), - Reason = "Reported minor engine issue, resolved after inspection", - RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), - RequestedBy = new Guid("29000000-0000-0000-0000-000000000005"), - Status = 2, - TypeCode = 0 - }); - }); - modelBuilder.Entity("Distribution.Models.Role", b => { b.Property("Id") @@ -1802,87 +1738,6 @@ namespace Distribution.Migrations }); }); - modelBuilder.Entity("Distribution.Models.Sale", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("char(36)"); - - b.Property("CompletedAt") - .HasColumnType("datetime(6)"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("CreatedByUserId") - .HasColumnType("char(36)"); - - b.Property("FK_RideId") - .HasColumnType("char(36)"); - - b.Property("FK_StoreId") - .HasColumnType("char(36)"); - - b.Property("FulfillImmediately") - .HasColumnType("tinyint(1)"); - - b.Property("IsActive") - .HasColumnType("tinyint(1)"); - - b.Property("PaymentStatus") - .HasColumnType("int"); - - b.Property("SaleDate") - .HasColumnType("datetime(6)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TotalAmount") - .HasColumnType("decimal(65,30)"); - - b.HasKey("Id"); - - b.HasIndex("CreatedByUserId"); - - b.HasIndex("FK_RideId"); - - b.HasIndex("FK_StoreId"); - - b.ToTable("Sales"); - - b.HasData( - new - { - Id = new Guid("32000000-0000-0000-0000-000000000001"), - CompletedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), - FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), - FulfillImmediately = false, - IsActive = true, - PaymentStatus = 2, - SaleDate = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Status = 1, - TotalAmount = 3000m - }, - new - { - Id = new Guid("32000000-0000-0000-0000-000000000002"), - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000003"), - FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), - FulfillImmediately = false, - IsActive = true, - PaymentStatus = 0, - SaleDate = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - Status = 0, - TotalAmount = 1200m - }); - }); - modelBuilder.Entity("Distribution.Models.SaleReturn", b => { b.Property("Id") @@ -1895,7 +1750,7 @@ namespace Distribution.Migrations b.Property("CreatedByUserId") .HasColumnType("char(36)"); - b.Property("FK_OrderId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); b.Property("IsActive") @@ -1911,7 +1766,7 @@ namespace Distribution.Migrations b.HasIndex("CreatedByUserId"); - b.HasIndex("FK_OrderId"); + b.HasIndex("FK_ShopPOId"); b.ToTable("SaleReturns"); @@ -1921,7 +1776,7 @@ namespace Distribution.Migrations Id = new Guid("51000000-0000-0000-0000-000000000001"), CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), IsActive = true, Mode = 0, TotalCreditAmount = 300m @@ -2153,10 +2008,10 @@ namespace Distribution.Migrations b.Property("FK_FreeItemId") .HasColumnType("char(36)"); - b.Property("FK_OrderId") + b.Property("FK_SchemeId") .HasColumnType("char(36)"); - b.Property("FK_SchemeId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); b.Property("FieldInvoiceId") @@ -2175,10 +2030,10 @@ namespace Distribution.Migrations b.HasIndex("FK_FreeItemId"); - b.HasIndex("FK_OrderId"); - b.HasIndex("FK_SchemeId"); + b.HasIndex("FK_ShopPOId"); + b.ToTable("SchemeRedemptions"); b.HasData( @@ -2187,14 +2042,180 @@ namespace Distribution.Migrations Id = new Guid("50000000-0000-0000-0000-000000000001"), DiscountAmount = 0m, FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), FreeItemCostValue = 40m, FreeQty = 1m, RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) }); }); + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000003"), + ConfirmedAt = new DateTime(2026, 8, 31, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + FulfilledAt = new DateTime(2026, 8, 31, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 2, + TotalAmount = 2400m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + Quantity = 20, + QuantityFulfilled = 20, + UnitPrice = 120m + }); + }); + modelBuilder.Entity("Distribution.Models.StockBalance", b => { b.Property("Id") @@ -2761,6 +2782,35 @@ namespace Distribution.Migrations }); }); + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + modelBuilder.Entity("Distribution.Models.Uom", b => { b.Property("Id") @@ -3205,18 +3255,6 @@ namespace Distribution.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Route", "Route") - .WithMany() - .HasForeignKey("FK_RouteId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Distribution.Models.Warehouse", "SourceWarehouse") - .WithMany() - .HasForeignKey("FK_SourceWarehouseId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - b.HasOne("Distribution.Models.Vehicle", "Vehicle") .WithMany() .HasForeignKey("FK_VehicleId") @@ -3225,30 +3263,26 @@ namespace Distribution.Migrations b.Navigation("DriverProfile"); - b.Navigation("Route"); - - b.Navigation("SourceWarehouse"); - b.Navigation("Vehicle"); }); modelBuilder.Entity("Distribution.Models.DeliveryTask", b => { - b.HasOne("Distribution.Models.Order", "Order") - .WithMany() - .HasForeignKey("FK_OrderId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - b.HasOne("Distribution.Models.DeliveryRun", "Ride") .WithMany() .HasForeignKey("FK_RideId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.Navigation("Order"); + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); b.Navigation("Ride"); + + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.DriverProfile", b => @@ -3300,6 +3334,17 @@ namespace Distribution.Migrations b.Navigation("PurchaseOrderItem"); }); + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + modelBuilder.Entity("Distribution.Models.Item", b => { b.HasOne("Distribution.Models.Uom", "BaseUom") @@ -3339,15 +3384,7 @@ namespace Distribution.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Warehouse", "SourceWarehouse") - .WithMany() - .HasForeignKey("FK_SourceWarehouseId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - b.Navigation("Ride"); - - b.Navigation("SourceWarehouse"); }); modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => @@ -3361,69 +3398,57 @@ namespace Distribution.Migrations b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") .WithMany("Items") .HasForeignKey("FK_LoadingSheetId") - .OnDelete(DeleteBehavior.Cascade) + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); b.Navigation("Item"); b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); }); - modelBuilder.Entity("Distribution.Models.Order", b => + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => { - b.HasOne("Distribution.Models.Sale", "Sale") - .WithMany() - .HasForeignKey("FK_SaleId") + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Store", "Store") + b.HasOne("Distribution.Models.ShopPO", "ShopPO") .WithMany() - .HasForeignKey("FK_StoreId") - .OnDelete(DeleteBehavior.Cascade) + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.Navigation("Sale"); + b.Navigation("LoadingSheet"); - b.Navigation("Store"); - }); - - modelBuilder.Entity("Distribution.Models.OrderItem", b => - { - b.HasOne("Distribution.Models.Item", "Item") - .WithMany() - .HasForeignKey("FK_ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Distribution.Models.Order", "Order") - .WithMany("OrderItems") - .HasForeignKey("FK_OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("Order"); + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.Payment", b => { - b.HasOne("Distribution.Models.Sale", "Sale") - .WithMany() - .HasForeignKey("FK_SaleId") - .OnDelete(DeleteBehavior.Cascade) + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Store", "Store") - .WithMany() - .HasForeignKey("FK_StoreId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Sale"); - - b.Navigation("Store"); + b.Navigation("Invoice"); }); modelBuilder.Entity("Distribution.Models.PriceList", b => @@ -3566,17 +3591,6 @@ namespace Distribution.Migrations b.Navigation("Region"); }); - modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => - { - b.HasOne("Distribution.Models.DeliveryRun", "Ride") - .WithMany() - .HasForeignKey("FK_RideId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Ride"); - }); - modelBuilder.Entity("Distribution.Models.RolePermission", b => { b.HasOne("Distribution.Models.Permission", "Permission") @@ -3640,32 +3654,6 @@ namespace Distribution.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Distribution.Models.Sale", b => - { - b.HasOne("Distribution.Models.User", "CreatedByUser") - .WithMany() - .HasForeignKey("CreatedByUserId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Distribution.Models.DeliveryRun", "Ride") - .WithMany() - .HasForeignKey("FK_RideId") - .OnDelete(DeleteBehavior.Restrict); - - b.HasOne("Distribution.Models.Store", "Store") - .WithMany() - .HasForeignKey("FK_StoreId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("CreatedByUser"); - - b.Navigation("Ride"); - - b.Navigation("Store"); - }); - modelBuilder.Entity("Distribution.Models.SaleReturn", b => { b.HasOne("Distribution.Models.User", "CreatedByUser") @@ -3674,15 +3662,15 @@ namespace Distribution.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Order", "Order") + b.HasOne("Distribution.Models.ShopPO", "ShopPO") .WithMany() - .HasForeignKey("FK_OrderId") + .HasForeignKey("FK_ShopPOId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); b.Navigation("CreatedByUser"); - b.Navigation("Order"); + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => @@ -3753,22 +3741,52 @@ namespace Distribution.Migrations .HasForeignKey("FK_FreeItemId") .OnDelete(DeleteBehavior.Restrict); - b.HasOne("Distribution.Models.Order", "Order") - .WithMany() - .HasForeignKey("FK_OrderId") - .OnDelete(DeleteBehavior.Restrict); - b.HasOne("Distribution.Models.Scheme", "Scheme") .WithMany("Redemptions") .HasForeignKey("FK_SchemeId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + b.Navigation("FreeItem"); - b.Navigation("Order"); - b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.StockBalance", b => @@ -4002,6 +4020,11 @@ namespace Distribution.Migrations b.Navigation("Items"); }); + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + modelBuilder.Entity("Distribution.Models.Item", b => { b.Navigation("Conversions"); @@ -4010,11 +4033,8 @@ namespace Distribution.Migrations modelBuilder.Entity("Distribution.Models.LoadingSheet", b => { b.Navigation("Items"); - }); - modelBuilder.Entity("Distribution.Models.Order", b => - { - b.Navigation("OrderItems"); + b.Navigation("Orders"); }); modelBuilder.Entity("Distribution.Models.PriceList", b => @@ -4044,6 +4064,11 @@ namespace Distribution.Migrations b.Navigation("Redemptions"); }); + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => { b.Navigation("Items"); diff --git a/Distribution/Models/DeliveryRun.cs b/Distribution/Models/DeliveryRun.cs index 492f3b6..66c801c 100644 --- a/Distribution/Models/DeliveryRun.cs +++ b/Distribution/Models/DeliveryRun.cs @@ -4,8 +4,7 @@ namespace Distribution.Models { public class DeliveryRun : Template { - public RideType RideType { get; set; } - public RideStatus Status { get; set; } = RideStatus.Draft; + public RideStatus Status { get; set; } = RideStatus.Open; public Guid FK_VehicleId { get; set; } [ForeignKey("FK_VehicleId")] @@ -15,19 +14,10 @@ namespace Distribution.Models [ForeignKey("FK_DriverProfileId")] public DriverProfile DriverProfile { get; set; } - public Guid FK_RouteId { get; set; } - [ForeignKey("FK_RouteId")] - public Route Route { get; set; } - - public Guid FK_SourceWarehouseId { get; set; } - [ForeignKey("FK_SourceWarehouseId")] - public Warehouse SourceWarehouse { get; set; } - public int Meterstart { get; set; } public int Meterend { get; set; } public DateTime? StartedAt { get; set; } - public DateTime? ActivatedAt { get; set; } public DateTime? ClosedAt { get; set; } } } diff --git a/Distribution/Models/DeliveryTask.cs b/Distribution/Models/DeliveryTask.cs index b28bdc1..e1e9bd1 100644 --- a/Distribution/Models/DeliveryTask.cs +++ b/Distribution/Models/DeliveryTask.cs @@ -8,9 +8,9 @@ namespace Distribution.Models [ForeignKey("FK_RideId")] public DeliveryRun Ride { get; set; } - public Guid FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order Order { get; set; } + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } public int Sequence { get; set; } public DeliveryTaskStatus Status { get; set; } = DeliveryTaskStatus.Pending; diff --git a/Distribution/Models/Enums.cs b/Distribution/Models/Enums.cs index ed2aa7f..2497221 100644 --- a/Distribution/Models/Enums.cs +++ b/Distribution/Models/Enums.cs @@ -3,32 +3,30 @@ namespace Distribution.Models public enum LocationType { Warehouse, Vehicle, External } - public enum KycStatus { Pending,Verified, Rejected } - public enum MovementType { Sale, CustomerReturn, Transfer, Damage, Adjustment, Load, PurchaseReceipt, PurchaseReturn } + public enum KycStatus { Pending, Verified, Rejected } - public enum LoadingSheetStatus { Pending, DispatchConfirmed, ReceiptConfirmed, DiscrepancyFlagged, Resolved } + public enum MovementType { Sale, CustomerReturn, Transfer, Damage, Adjustment, Load, PurchaseReceipt, PurchaseReturn } - public enum RideType { Delivery, Sale } + public enum LoadingSheetStatus { Planned, Confirmed } - public enum RideStatus { Draft, Open, Active, CancelRequested, Cancelled, Closed } + public enum RideStatus { Open, Cancelled, Closed } public enum CancelRequestType { VehicleBreakdown, DriverUnavailable, RouteIssue, Other } - public enum CancelRequestStatus { Pending, Approved, Rejected } - public enum PurchaseOrderStatus { Issued, PartiallyReceived, Received, Closed, Cancelled } - public enum SaleStatus { Pending, Completed, Cancelled } + public enum ShopPOStatus { Pending, PartiallyFulfilled, Fulfilled, Cancelled } - public enum OrderStatus { Pending, PartiallyFulfilled, Fulfilled, Cancelled } + public enum InvoiceStatus { Draft, Printed, Finalized } public enum PaymentStatus { Pending, PartiallyPaid, Paid } - public enum PaymentMethod { Cash, Credit } + public enum PaymentMethod { Cash, Cheque, Credit } - public enum DeliveryTaskStatus - { Pending, Delivered, PartiallyDelivered, Failed} + public enum EntryMode { RealTime, DayEndManual } + + public enum DeliveryTaskStatus { Pending, Delivered, PartiallyDelivered, Failed } public enum ReturnMode { CreditDeduction, ItemExchange } @@ -41,4 +39,10 @@ namespace Distribution.Models public enum SupplierClaimIssueType { Damaged, Short, Expired, WrongItem, Other } public enum SupplierClaimResolutionType { Replacement, Credit, Refund, PriceAdjustment } + + /// + /// ModeA: Invoice auto-created when ShopPO is confirmed. + /// ModeB: Invoice created as a separate explicit step. + /// + public enum InvoiceCreationMode { ModeA, ModeB } } diff --git a/Distribution/Models/Invoice.cs b/Distribution/Models/Invoice.cs new file mode 100644 index 0000000..dc60e80 --- /dev/null +++ b/Distribution/Models/Invoice.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Distribution.Models +{ + public class Invoice : Template + { + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } + + public InvoiceStatus Status { get; set; } = InvoiceStatus.Draft; + public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending; + + public Guid CreatedBy { get; set; } + + public DateTime? PrintedAt { get; set; } + public Guid? PrintedBy { get; set; } + + public DateTime? FinalizedAt { get; set; } + public Guid? FinalizedBy { get; set; } + + public decimal TotalAmount { get; set; } + + public ICollection Payments { get; set; } = new List(); + } +} diff --git a/Distribution/Models/LoadingSheet.cs b/Distribution/Models/LoadingSheet.cs index a74f085..db88cc1 100644 --- a/Distribution/Models/LoadingSheet.cs +++ b/Distribution/Models/LoadingSheet.cs @@ -8,17 +8,15 @@ namespace Distribution.Models [ForeignKey("FK_RideId")] public DeliveryRun Ride { get; set; } - public Guid FK_SourceWarehouseId { get; set; } - [ForeignKey("FK_SourceWarehouseId")] - public Warehouse SourceWarehouse { get; set; } + public LoadingSheetStatus Status { get; set; } = LoadingSheetStatus.Planned; - public LoadingSheetStatus Status { get; set; } = LoadingSheetStatus.Pending; + public Guid PopulatedBy { get; set; } + public DateTime PopulatedAt { get; set; } - public DateTime? DispatchConfirmedAt { get; set; } - public Guid? DispatchConfirmedBy { get; set; } - public DateTime? ReceiptConfirmedAt { get; set; } - public Guid? ReceiptConfirmedBy { get; set; } + public DateTime? ConfirmedAt { get; set; } + public Guid? ConfirmedBy { get; set; } public List Items { get; set; } = []; + public List Orders { get; set; } = []; } } diff --git a/Distribution/Models/LoadingSheetItem.cs b/Distribution/Models/LoadingSheetItem.cs index 2976dbf..3f9df91 100644 --- a/Distribution/Models/LoadingSheetItem.cs +++ b/Distribution/Models/LoadingSheetItem.cs @@ -2,10 +2,8 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Distribution.Models { - public class LoadingSheetItem + public class LoadingSheetItem : Template { - public Guid Id { get; set; } = Guid.NewGuid(); - public Guid FK_LoadingSheetId { get; set; } [ForeignKey("FK_LoadingSheetId")] public LoadingSheet LoadingSheet { get; set; } @@ -14,8 +12,14 @@ namespace Distribution.Models [ForeignKey("FK_ItemId")] public Item Item { get; set; } + public Guid FK_WarehouseId { get; set; } + [ForeignKey("FK_WarehouseId")] + public Warehouse Warehouse { get; set; } + + public Guid? FK_ShopPOItemId { get; set; } + [ForeignKey("FK_ShopPOItemId")] + public ShopPOItem? ShopPOItem { get; set; } + public decimal QuantityDispatched { get; set; } - public decimal? QuantityReceived { get; set; } - public decimal? QuantityResolved { get; set; } } } diff --git a/Distribution/Models/LoadingSheetOrder.cs b/Distribution/Models/LoadingSheetOrder.cs new file mode 100644 index 0000000..dca6d18 --- /dev/null +++ b/Distribution/Models/LoadingSheetOrder.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Distribution.Models +{ + public class LoadingSheetOrder + { + public Guid FK_LoadingSheetId { get; set; } + [ForeignKey("FK_LoadingSheetId")] + public LoadingSheet LoadingSheet { get; set; } + + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } + } +} diff --git a/Distribution/Models/Order.cs b/Distribution/Models/Order.cs deleted file mode 100644 index ef7448f..0000000 --- a/Distribution/Models/Order.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Distribution.Models -{ - public class Order : Template - { - public Guid FK_SaleId { get; set; } - [ForeignKey("FK_SaleId")] - public Sale Sale { get; set; } - - public DateTime OrderDate { get; set; } - public Guid FK_StoreId { get; set; } - [ForeignKey("FK_StoreId")] - public Store Store { get; set; } - public decimal TotalAmount { get; set; } - public OrderStatus Status { get; set; } = OrderStatus.Pending; - public DateTime? FulfilledAt { get; set; } - - public ICollection OrderItems { get; set; } = new List(); - } -} diff --git a/Distribution/Models/Payment.cs b/Distribution/Models/Payment.cs index 79a7bac..56f46cb 100644 --- a/Distribution/Models/Payment.cs +++ b/Distribution/Models/Payment.cs @@ -4,17 +4,17 @@ namespace Distribution.Models { public class Payment : Template { - public Guid FK_SaleId { get; set; } - [ForeignKey("FK_SaleId")] - public Sale Sale { get; set; } - - public Guid FK_StoreId { get; set; } - [ForeignKey("FK_StoreId")] - public Store Store { get; set; } + public Guid FK_InvoiceId { get; set; } + [ForeignKey("FK_InvoiceId")] + public Invoice Invoice { get; set; } public decimal Amount { get; set; } public PaymentMethod Method { get; set; } + public EntryMode EntryMode { get; set; } = EntryMode.RealTime; + public string? ChequeNumber { get; set; } + public DateTime? ChequeDate { get; set; } public DateTime CollectedAt { get; set; } public Guid CollectedBy { get; set; } + public Guid? RecordedBy { get; set; } } } diff --git a/Distribution/Models/RideCancelRequest.cs b/Distribution/Models/RideCancelRequest.cs deleted file mode 100644 index 0692c83..0000000 --- a/Distribution/Models/RideCancelRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Distribution.Models -{ - public class RideCancelRequest - { - public Guid Id { get; set; } = Guid.NewGuid(); - - public Guid FK_RideId { get; set; } - [ForeignKey("FK_RideId")] - public DeliveryRun Ride { get; set; } - - public CancelRequestType TypeCode { get; set; } - public string Reason { get; set; } - - public Guid RequestedBy { get; set; } - public DateTime RequestedAt { get; set; } = DateTime.Now; - - public CancelRequestStatus Status { get; set; } = CancelRequestStatus.Pending; - public Guid? ApprovedBy { get; set; } - public DateTime? ApprovedAt { get; set; } - } -} diff --git a/Distribution/Models/Sale.cs b/Distribution/Models/Sale.cs deleted file mode 100644 index 68eaae8..0000000 --- a/Distribution/Models/Sale.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Distribution.Models -{ - public class Sale : Template - { - public DateTime SaleDate { get; set; } - - public Guid FK_StoreId { get; set; } - [ForeignKey("FK_StoreId")] - public Store Store { get; set; } - - public Guid CreatedByUserId { get; set; } - [ForeignKey("CreatedByUserId")] - public User CreatedByUser { get; set; } - - public Guid? FK_RideId { get; set; } - [ForeignKey("FK_RideId")] - public DeliveryRun? Ride { get; set; } - - public decimal TotalAmount { get; set; } - public SaleStatus Status { get; set; } = SaleStatus.Pending; - public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending; - public bool FulfillImmediately { get; set; } - public DateTime? CompletedAt { get; set; } - } -} diff --git a/Distribution/Models/SaleReturn.cs b/Distribution/Models/SaleReturn.cs index 48375b6..0d5e58a 100644 --- a/Distribution/Models/SaleReturn.cs +++ b/Distribution/Models/SaleReturn.cs @@ -8,9 +8,9 @@ namespace Distribution.Models /// public class SaleReturn : Template { - public Guid FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order Order { get; set; } + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } public ReturnMode Mode { get; set; } diff --git a/Distribution/Models/SchemeRedemption.cs b/Distribution/Models/SchemeRedemption.cs index 78dbf7b..6aeaff2 100644 --- a/Distribution/Models/SchemeRedemption.cs +++ b/Distribution/Models/SchemeRedemption.cs @@ -10,9 +10,9 @@ namespace Distribution.Models [ForeignKey("FK_SchemeId")] public Scheme Scheme { get; set; } - public Guid? FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order? Order { get; set; } + public Guid? FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO? ShopPO { get; set; } /// Placeholder for the future field-invoice module — no FieldInvoice entity exists yet. public Guid? FieldInvoiceId { get; set; } diff --git a/Distribution/Models/ShopPO.cs b/Distribution/Models/ShopPO.cs new file mode 100644 index 0000000..f30fa0d --- /dev/null +++ b/Distribution/Models/ShopPO.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Distribution.Models +{ + public class ShopPO : Template + { + public Guid FK_StoreId { get; set; } + [ForeignKey("FK_StoreId")] + public Store Store { get; set; } + + public Guid RaisedById { get; set; } + + public Guid? InvoiceId { get; set; } + + public decimal TotalAmount { get; set; } + public ShopPOStatus Status { get; set; } = ShopPOStatus.Pending; + + public DateTime? ConfirmedAt { get; set; } + public Guid? ConfirmedBy { get; set; } + + public DateTime? FulfilledAt { get; set; } + + public ICollection Items { get; set; } = new List(); + } +} diff --git a/Distribution/Models/OrderItem.cs b/Distribution/Models/ShopPOItem.cs similarity index 58% rename from Distribution/Models/OrderItem.cs rename to Distribution/Models/ShopPOItem.cs index 07dfa15..0b7b7ec 100644 --- a/Distribution/Models/OrderItem.cs +++ b/Distribution/Models/ShopPOItem.cs @@ -1,15 +1,17 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; namespace Distribution.Models { - public class OrderItem : Template + public class ShopPOItem : Template { - public Guid FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order Order { get; set; } + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } + public Guid FK_ItemId { get; set; } [ForeignKey("FK_ItemId")] public Item Item { get; set; } + public int Quantity { get; set; } public int QuantityFulfilled { get; set; } = 0; public decimal UnitPrice { get; set; } diff --git a/Distribution/Models/SysConfig.cs b/Distribution/Models/SysConfig.cs new file mode 100644 index 0000000..379ba4d --- /dev/null +++ b/Distribution/Models/SysConfig.cs @@ -0,0 +1,10 @@ +namespace Distribution.Models +{ + public class SysConfig + { + public string Key { get; set; } + public string Value { get; set; } + public DateTime UpdatedAt { get; set; } = DateTime.Now; + public Guid? UpdatedBy { get; set; } + } +} diff --git a/Distribution/Program.cs b/Distribution/Program.cs index e93eb77..7308d1a 100644 --- a/Distribution/Program.cs +++ b/Distribution/Program.cs @@ -10,7 +10,8 @@ using Distribution.Features.DriverComplianceConfig; using Distribution.Features.DriverProfile; using Distribution.Features.Grn; using Distribution.Features.Item; -using Distribution.Features.Order; +using Distribution.Features.ShopPO; +using Distribution.Features.Invoice; using Distribution.Features.PriceList; using Distribution.Features.Po; using Distribution.Features.PurchaseReturn; @@ -22,7 +23,6 @@ using Distribution.Features.LoadingEvent; using Distribution.Features.Ride; using Distribution.Features.Role; using Distribution.Features.Route; -using Distribution.Features.Sale; using Distribution.Features.Scheme; using Distribution.Features.Store; using Distribution.Features.Store.Kyc; @@ -32,6 +32,7 @@ using Distribution.Features.Uom; using Distribution.Features.User; using Distribution.Features.Vehicle; using Distribution.Features.Stock; +using Distribution.Features.SysConfig; using Distribution.Features.Warehouse; using Distribution.Infra.Authorization; using Distribution.Infra.UoW; @@ -52,8 +53,8 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -65,7 +66,6 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -85,8 +85,8 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Distribution/appsettings.json b/Distribution/appsettings.json index 8efc9f8..f2b1778 100644 --- a/Distribution/appsettings.json +++ b/Distribution/appsettings.json @@ -1,7 +1,7 @@ { - "Urls": "http://localhost:5089", + "Urls": "http://localhost:8802", "ConnectionStrings": { - "DefaultConnection": "Server=187.127.102.190;Port=3306;Database=distribution_db;User=kalana;Password=kalana@hexdive" + "DefaultConnection": "Server=187.127.102.190;Port=3306;Database=distribution;User=kalana;Password=kalana@hexdive" }, "Logging": { "LogLevel": { @@ -21,7 +21,7 @@ }, "AuthHex": { - "BaseUrl": "http://localhost:6102" + "BaseUrl": "http://localhost:8801" }, "StoreManagement": { "UnverifiedKycOrderThreshold": 0 diff --git a/Distribution/docs/refactor_docs/refactor_plan.md b/Distribution/docs/refactor_docs/refactor_plan.md new file mode 100644 index 0000000..49bf499 --- /dev/null +++ b/Distribution/docs/refactor_docs/refactor_plan.md @@ -0,0 +1,737 @@ +# Refactor Implementation Plan + +**Status**: Implementation complete — migration pending (see Phase 5) +**Design docs**: [order_invoice_lifecycle.md](./order_invoice_lifecycle.md), [loading_event.md](./loading_event.md), [dispatch_pipeline.md](./dispatch_pipeline.md), [ride_lifecycle.md](./ride_lifecycle.md) + +| Phase | Title | Status | +|-------|-------|--------| +| 1 | Enums | ✅ Done | +| 2 | Remove Sale | ✅ Done | +| 3 | Model Changes | ✅ Done | +| 4 | DbContext | ✅ Done | +| 5 | Migration | ⚠️ Migration created — `dotnet ef database update` failing (FK drop error — fix applied 2026-09-17) | +| 6 | Invoice Feature | ✅ Done (GET list/detail only; create/print/finalize endpoints pending) | +| 7 | ShopPO Feature | ✅ Done (GET list/detail only; confirm/cancel/items endpoints pending) | +| 8 | Payment Feature | ✅ Done | +| 9 | LoadingEvent Overhaul | ✅ Done | +| 10 | Ride Overhaul | ✅ Done | +| 11 | SysConfig + InvoiceCreationMode | ✅ Done (replaces original Program.cs/appsettings plan; implemented as DB-backed key-value store) | +| 12 | Permission Seeding | ⏳ Pending | + +--- + +## Scope + +Replace the Sale/Order/LoadingSheet pipeline with a unified ShopPO → Invoice → LoadingSheet flow: + +- `Order` entity renamed to `ShopPO` throughout +- `Sale` entity and feature removed entirely +- `Invoice` entity introduced as the billing document +- `Payment` moved from Sale to Invoice +- `LoadingSheet` overhauled: dispatcher-triggered, multi-PO, per-item warehouse +- `DeliveryRun` (Ride) simplified: no route, no type, no Active state +- `SaleReturn` FK renamed only — full redesign is a separate pass + +--- + +## Execution Order + +``` +Phase 1 → Phase 2 → Phase 3 → Phase 4 → Phase 5 (migration) +→ Phase 6, 7, 8, 9, 10 (independent after migration) +→ Phase 11 → Phase 12 +``` + +Phases 6–10 have no dependencies on each other and can be worked in parallel. + +--- + +## Phase 1 — Enums + +**File**: `Models/Enums.cs` + +| Enum | Action | New Values | +|---|---|---| +| `LoadingSheetStatus` | Replace all values | `Planned`, `Confirmed` | +| `RideStatus` | Remove `Draft`, `Active`, `CancelRequested` | Keep `Open`, `Cancelled`, `Closed` | +| `RideType` | **Delete entire enum** | — | +| `InvoiceStatus` | **Add new** | `Draft`, `Printed`, `Finalized` | +| `OrderStatus` | Rename to `ShopPOStatus` | Keep values: `Pending`, `PartiallyFulfilled`, `Fulfilled`, `Cancelled` | +| `SaleStatus` | **Delete entire enum** | — | + +--- + +## Phase 2 — Remove Sale + +Sale has no downstream model dependencies except `Order.FK_SaleId` and `Payment.FK_SaleId` — both handled in Phase 3. + +### Delete files +- `Models/Sale.cs` +- `Features/Sale/SaleController.cs` +- `Features/Sale/SaleService.cs` +- `Features/Sale/ISaleRepository.cs` +- `Features/Sale/SaleRepository.cs` +- `Features/Sale/SaleDTOs.cs` + +### Update `Data/AppDBContext.cs` +- Remove `DbSet Sales` +- Remove all Fluent API config blocks referencing `Sale` + +### Update `Program.cs` +- Remove `ISaleRepository` / `SaleRepository` registration +- Remove `SaleService` registration + +--- + +## Phase 3 — Model Changes + +### 3.1 Rename `Order` → `ShopPO` + +Create `Models/ShopPO.cs`. Delete `Models/Order.cs`. + +```csharp +public class ShopPO : Template +{ + public Guid FK_StoreId { get; set; } + public Store Store { get; set; } + + public Guid RaisedById { get; set; } // agent who created the PO + + public Guid? InvoiceId { get; set; } // set when Invoice is created — NO FK constraint + + public decimal TotalAmount { get; set; } + + public ShopPOStatus Status { get; set; } = ShopPOStatus.Pending; + + public DateTime? ConfirmedAt { get; set; } // null = Shop PO, set = Confirmed PO + public Guid? ConfirmedBy { get; set; } + + public DateTime? FulfilledAt { get; set; } + + public ICollection Items { get; set; } +} +``` + +Removed from current `Order.cs`: `FK_SaleId`, `OrderDate` (use `CreatedAt` from Template). + +### 3.2 Rename `OrderItem` → `ShopPOItem` + +Create `Models/ShopPOItem.cs`. Delete `Models/OrderItem.cs`. + +```csharp +public class ShopPOItem : Template // Template gives Id, IsActive, CreatedAt +{ + public Guid FK_ShopPOId { get; set; } + public ShopPO ShopPO { get; set; } + + public Guid FK_ItemId { get; set; } + public Item Item { get; set; } + + public int Quantity { get; set; } + public int QuantityFulfilled { get; set; } = 0; + public decimal UnitPrice { get; set; } +} +``` + +No property changes beyond the FK rename. The existing `IsActive` (from Template) already supports versioning. + +### 3.3 Update `Models/LoadingSheet.cs` + +Remove: +- `FK_SourceWarehouseId` and its navigation property +- `DispatchConfirmedAt`, `DispatchConfirmedBy` +- `ReceiptConfirmedAt`, `ReceiptConfirmedBy` + +Add: +- `PopulatedBy` (Guid) +- `PopulatedAt` (DateTime) +- `ConfirmedAt` (DateTime?) +- `ConfirmedBy` (Guid?) + +`FK_RideId` already exists — no change needed. + +### 3.4 Update `Models/LoadingSheetItem.cs` + +Make it inherit `Template` (adds `Id` PK, `IsActive`, `CreatedAt`). + +Remove: +- `QuantityReceived` +- `QuantityResolved` + +Add: +- `FK_WarehouseId` (Guid, required) — warehouse this item is loaded from +- `FK_ShopPOItemId` (Guid?, nullable) — traces back to source `ShopPOItem` + +### 3.5 New `Models/LoadingSheetOrder.cs` + +```csharp +public class LoadingSheetOrder +{ + public Guid FK_LoadingSheetId { get; set; } + public LoadingSheet LoadingSheet { get; set; } + + public Guid FK_ShopPOId { get; set; } + public ShopPO ShopPO { get; set; } +} +``` + +Composite PK on `(FK_LoadingSheetId, FK_ShopPOId)` — configured in DbContext. + +### 3.6 Update `Models/DeliveryRun.cs` + +Remove: +- `RideType` (enum deleted in Phase 1) +- `FK_RouteId` and its navigation property +- `FK_SourceWarehouseId` and its navigation property +- `ActivatedAt` + +Keep: `FK_VehicleId`, `FK_DriverProfileId`, `Status`, `Meterstart`, `Meterend`, `StartedAt`, `ClosedAt`. + +### 3.7 Update `Models/Payment.cs` + +Remove: +- `FK_SaleId` +- `FK_StoreId` (derivable via Invoice → ShopPO → Store) + +Add: +- `FK_InvoiceId` (Guid, required) + +### 3.8 New `Models/Invoice.cs` + +```csharp +public class Invoice : Template +{ + public Guid FK_ShopPOId { get; set; } + public ShopPO ShopPO { get; set; } + + public InvoiceStatus Status { get; set; } = InvoiceStatus.Draft; + public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending; + + public Guid CreatedBy { get; set; } + + public DateTime? PrintedAt { get; set; } + public Guid? PrintedBy { get; set; } + + public DateTime? FinalizedAt { get; set; } + public Guid? FinalizedBy { get; set; } + + public decimal TotalAmount { get; set; } + + public ICollection Payments { get; set; } +} +``` + +### 3.9 FK Renames on Other Models + +These models reference `Order` only — no Sale reference. Rename FK and navigation property only: + +| File | Change | +|---|---| +| `Models/DeliveryTask.cs` | `FK_OrderId` → `FK_ShopPOId`, navigation `Order` → `ShopPO` | +| `Models/SchemeRedemption.cs` | `FK_OrderId` → `FK_ShopPOId`, navigation `Order` → `ShopPO` | +| `Models/SaleReturn.cs` | `FK_OrderId` → `FK_ShopPOId`, navigation `Order` → `ShopPO` | + +--- + +## Phase 4 — DbContext (`Data/AppDBContext.cs`) + +### DbSet changes +```csharp +// Remove +DbSet Sales +DbSet Orders +DbSet OrderItems + +// Add +DbSet ShopPOs +DbSet ShopPOItems +DbSet Invoices +DbSet LoadingSheetOrders +``` + +### Fluent API changes + +**`ShopPO`** +- `ShopPO.InvoiceId`: configure as plain column with no FK constraint — `builder.Property(x => x.InvoiceId).HasColumnName("InvoiceId")` (no `HasForeignKey`) +- `ShopPO` → `Store`: Restrict delete +- Remove previous unique index on `FK_SaleId` + +**`ShopPOItem`** +- Remove unique composite index on `(FK_OrderId, FK_ItemId)` — versioning requires multiple rows with same combo +- `ShopPOItem` → `ShopPO`: Restrict delete +- `ShopPOItem` → `Item`: Restrict delete + +**`Invoice`** +- `Invoice` → `ShopPO`: Restrict delete +- One-to-one: one ShopPO has at most one Invoice + +**`LoadingSheetOrder`** +- Composite PK: `(FK_LoadingSheetId, FK_ShopPOId)` +- `LoadingSheetOrder` → `LoadingSheet`: Restrict delete +- `LoadingSheetOrder` → `ShopPO`: Restrict delete + +**`LoadingSheet`** +- Remove: Warehouse relation for `FK_SourceWarehouseId` + +**`LoadingSheetItem`** +- Add: `FK_WarehouseId` → Warehouse (Restrict delete) +- Add: `FK_ShopPOItemId` → ShopPOItem (SetNull — nullable FK) + +**`Payment`** +- Remove: Sale relation for `FK_SaleId`, Store relation for `FK_StoreId` +- Add: `FK_InvoiceId` → Invoice (Restrict delete) + +**`DeliveryRun`** +- Remove: Route relation for `FK_RouteId`, Warehouse relation for `FK_SourceWarehouseId`, RideType property + +**`DeliveryTask`**, **`SchemeRedemption`**, **`SaleReturn`** +- Update FK navigation references from `Order` → `ShopPO` + +--- + +## Phase 5 — Migration + +One EF Core migration: `RefactorSalesToShopPOAndInvoice` + +Key DDL generated: +```sql +-- ShopPO (was Orders table) +RENAME TABLE Orders TO ShopPOs; +ALTER TABLE ShopPOs DROP COLUMN FK_SaleId, DROP COLUMN OrderDate; +ALTER TABLE ShopPOs ADD RaisedById CHAR(36) NOT NULL, + InvoiceId CHAR(36) NULL, + ConfirmedAt DATETIME NULL, + ConfirmedBy CHAR(36) NULL; +ALTER TABLE ShopPOs RENAME COLUMN Status TO Status; -- enum value update handled by app +DROP INDEX IX_Orders_FK_SaleId ON ShopPOs; + +-- ShopPOItems (was OrderItems table) +RENAME TABLE OrderItems TO ShopPOItems; +ALTER TABLE ShopPOItems RENAME COLUMN FK_OrderId TO FK_ShopPOId; +DROP INDEX IX_OrderItems_FK_OrderId_FK_ItemId ON ShopPOItems; -- remove unique constraint + +-- LoadingSheets +ALTER TABLE LoadingSheets DROP COLUMN FK_SourceWarehouseId, + DROP COLUMN DispatchConfirmedAt, DROP COLUMN DispatchConfirmedBy, + DROP COLUMN ReceiptConfirmedAt, DROP COLUMN ReceiptConfirmedBy; +ALTER TABLE LoadingSheets ADD PopulatedBy CHAR(36) NOT NULL, + PopulatedAt DATETIME NOT NULL, + ConfirmedAt DATETIME NULL, + ConfirmedBy CHAR(36) NULL; + +-- LoadingSheetItems +ALTER TABLE LoadingSheetItems DROP COLUMN QuantityReceived, DROP COLUMN QuantityResolved; +ALTER TABLE LoadingSheetItems ADD FK_WarehouseId CHAR(36) NOT NULL, + FK_ShopPOItemId CHAR(36) NULL, + IsActive TINYINT(1) NOT NULL DEFAULT 1, + CreatedAt DATETIME NOT NULL; + +-- DeliveryRuns +ALTER TABLE DeliveryRuns DROP COLUMN RideType, DROP COLUMN FK_RouteId, + DROP COLUMN FK_SourceWarehouseId, DROP COLUMN ActivatedAt; + +-- Payments +ALTER TABLE Payments DROP COLUMN FK_SaleId, DROP COLUMN FK_StoreId; +ALTER TABLE Payments ADD FK_InvoiceId CHAR(36) NOT NULL; + +-- DeliveryTasks, SchemeRedemptions, SaleReturns +ALTER TABLE DeliveryTasks RENAME COLUMN FK_OrderId TO FK_ShopPOId; +ALTER TABLE SchemeRedemptions RENAME COLUMN FK_OrderId TO FK_ShopPOId; +ALTER TABLE SaleReturns RENAME COLUMN FK_OrderId TO FK_ShopPOId; + +-- New tables +CREATE TABLE Invoices (...); +CREATE TABLE LoadingSheetOrders (FK_LoadingSheetId, FK_ShopPOId, PRIMARY KEY (FK_LoadingSheetId, FK_ShopPOId)); + +-- Drop Sale table +DROP TABLE Sales; +``` + +--- + +## Phase 6 — New Invoice Feature + +**New folder**: `Features/Invoice/` + +### `InvoiceDTOs.cs` + +```csharp +// Mode B create +record CreateInvoiceRequest(Guid ShopPOId); + +// Mode A — called internally from ShopPOService, no separate request needed + +record InvoiceResponse(Guid Id, Guid ShopPOId, InvoiceStatus Status, + PaymentStatus PaymentStatus, Guid CreatedBy, + DateTime? PrintedAt, Guid? PrintedBy, + DateTime? FinalizedAt, Guid? FinalizedBy, + decimal TotalAmount, DateTime CreatedAt); + +// Finalize payload — exact adjustment fields TBD (free issues handling open) +record FinalizeInvoiceRequest(List Adjustments); +record InvoiceItemAdjustment(Guid ShopPOItemId, int AdjustedQuantity, string? Note); +``` + +### `IInvoiceRepository.cs` +- `GetByIdAsync(Guid id)` +- `GetByShopPOIdAsync(Guid shopPOId)` +- `GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize)` +- `AddAsync(Invoice invoice)` +- `Update(Invoice invoice)` + +### `InvoiceRepository.cs` +EF implementation of above. + +### `InvoiceService.cs` +- `CreateAsync(Guid shopPOId, Guid createdBy)` — Mode B; validates ShopPO is Confirmed, no Invoice exists yet; sets `ShopPO.InvoiceId` in same transaction +- `PrintAsync(Guid id)` — `Draft → Printed`; sets `PrintedAt`/`PrintedBy` +- `FinalizeAsync(Guid id, FinalizeInvoiceRequest request)` — `Printed → Finalized`; applies adjustments, locks `TotalAmount`, sets `FinalizedAt`/`FinalizedBy` + +### `InvoiceController.cs` + +| Method | Route | Mode gate | Description | +|---|---|---|---| +| POST | `/api/invoices` | Mode B only | Create Invoice for a Confirmed ShopPO | +| GET | `/api/invoices` | Any | List with filters | +| GET | `/api/invoices/{id}` | Any | Get detail | +| POST | `/api/invoices/{id}/print` | Any | `Draft → Printed` | +| POST | `/api/invoices/{id}/finalize` | Any | `Printed → Finalized` | + +--- + +## Phase 7 — ShopPO Feature (replaces Order) + +**Delete**: `Features/Order/` (all files) +**New folder**: `Features/ShopPO/` + +### `ShopPODTOs.cs` + +```csharp +record CreateShopPORequest(Guid StoreId, List Items); +record ShopPOItemRequest(Guid ItemId, int Quantity, decimal? UnitPrice = null); + +record UpdateShopPOItemsRequest(List Items); // versioned rewrite + +record ShopPOResponse(Guid Id, Guid StoreId, Guid RaisedById, + Guid? InvoiceId, decimal TotalAmount, ShopPOStatus Status, + DateTime? ConfirmedAt, Guid? ConfirmedBy, DateTime? FulfilledAt, + List Items, bool IsActive, DateTime CreatedAt); + +record ShopPOItemResponse(Guid Id, Guid ItemId, int Quantity, + int QuantityFulfilled, decimal UnitPrice, bool IsActive); +``` + +### `IShopPORepository.cs` +- `GetByIdAsync(Guid id)` — active items only by default +- `GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize)` +- `GetConfirmedWithoutInvoiceAsync(Guid? agentId, Guid? routeId, Guid? shopId)` — used by Mode B invoice creation and LoadingSheet population +- `AddAsync(ShopPO po)` +- `ReplaceItemsAsync(Guid shopPOId, List newItems)` — soft-delete current IsActive rows, insert fresh set +- `Update(ShopPO po)` + +### `ShopPOService.cs` +- `CreateAsync(CreateShopPORequest request)` — creates ShopPO with `ConfirmedAt = null`; resolves item prices via `PriceListService` +- `UpdateItemsAsync(Guid id, UpdateShopPOItemsRequest request)` — only while `ConfirmedAt == null`; calls versioned replace +- `ConfirmAsync(Guid id)` — Mode B: sets `ConfirmedAt`/`ConfirmedBy`; locks items +- `ConfirmAndCreateInvoiceAsync(Guid id)` — Mode A: confirm + create Invoice atomically in one transaction; sets `ShopPO.InvoiceId` +- `CancelAsync(Guid id)` — sets `Status = Cancelled`; throws if linked Invoice exists (cascade rules not yet defined — see Open Items) +- `GetAllAsync(...)`, `GetByIdAsync(...)` + +### `ShopPOController.cs` + +| Method | Route | Who | Description | +|---|---|---|---| +| POST | `/api/shop-pos` | Agent | Create Shop PO | +| GET | `/api/shop-pos` | Any | List (filter: agentId, routeId, shopId, confirmed) | +| GET | `/api/shop-pos/{id}` | Any | Get detail | +| PUT | `/api/shop-pos/{id}/items` | Agent | Versioned item rewrite (Shop PO only) | +| POST | `/api/shop-pos/{id}/confirm` | Office | Mode B — confirm PO only | +| POST | `/api/shop-pos/{id}/confirm-and-create-invoice` | Office | Mode A — atomic confirm + invoice | +| POST | `/api/shop-pos/{id}/cancel` | Agent/Office | Cancel Shop PO or Confirmed PO | + +Mode A endpoint returns `405 Method Not Allowed` when `InvoiceCreationMode = "B"` and vice versa. + +--- + +## Phase 8 — Update Payment Feature + +### `Models/Payment.cs` +Already updated in Phase 3 (`FK_InvoiceId`, removed `FK_SaleId` and `FK_StoreId`). + +### `PaymentDTOs.cs` +```csharp +// Before: CreatePaymentRequest(Amount, Method) against saleId in route +// After: CreatePaymentRequest(Amount, Method) against invoiceId in route +record CreatePaymentRequest(decimal Amount, PaymentMethod Method); +record PaymentResponse(Guid Id, Guid InvoiceId, decimal Amount, + PaymentMethod Method, DateTime CollectedAt, Guid CollectedBy); +``` + +### `IPaymentRepository.cs` / `PaymentRepository.cs` +- Replace `GetBySaleIdAsync` → `GetByInvoiceIdAsync(Guid invoiceId)` +- `AddAsync`, `Update` unchanged + +### `PaymentService.cs` +On `RecordPaymentAsync(Guid invoiceId, CreatePaymentRequest request)`: +1. Validate Invoice exists and is not `Cancelled`/voided +2. Add `Payment` record with `FK_InvoiceId` +3. Sum all payments for this Invoice +4. Recalculate `Invoice.PaymentStatus`: + - `sum == 0` → `Pending` + - `sum < Invoice.TotalAmount` → `PartiallyPaid` + - `sum >= Invoice.TotalAmount` → `Paid` +5. Update `Invoice.PaymentStatus` in same transaction + +### `PaymentController.cs` +Change route from `/api/sales/{saleId}/payments` → `/api/invoices/{invoiceId}/payments` + +| Method | Route | Description | +|---|---|---| +| POST | `/api/invoices/{invoiceId}/payments` | Record payment against invoice | +| GET | `/api/invoices/{invoiceId}/payments` | List payments for invoice | + +--- + +## Phase 9 — Overhaul LoadingEvent Feature + +Near-complete rewrite of service and controller. See `loading_event.md` for full state machine. + +### `LoadingSheetDTOs.cs` — replace with + +```csharp +record PopulateRequest(Guid RideId, Guid? RouteId, Guid? AgentId, Guid? ShopId); + +record UpdateLoadingSheetItemsRequest(List Items); +record LoadingSheetItemInput(Guid ItemId, Guid WarehouseId, decimal Quantity, Guid? ShopPOItemId = null); + +record LoadingSheetResponse(Guid Id, Guid RideId, LoadingSheetStatus Status, + Guid PopulatedBy, DateTime PopulatedAt, + DateTime? ConfirmedAt, Guid? ConfirmedBy, + List SourceShopPOIds, + List Items, + DateTime CreatedAt); + +record LoadingSheetItemResponse(Guid Id, Guid ItemId, Guid WarehouseId, + decimal QuantityDispatched, Guid? ShopPOItemId, bool IsActive); +``` + +### `ILoadingSheetRepository.cs` / `LoadingSheetRepository.cs` — replace with + +- `PopulateAsync(PopulateRequest request, Guid populatedBy)` — finds all Confirmed ShopPOs matching filters, creates one `LoadingSheet` at `Planned`, populates `LoadingSheetItem` rows from active `ShopPOItem` lines, inserts `LoadingSheetOrder` rows +- `GetAllAsync(Guid? routeId, Guid? agentId, Guid? shopId, Guid? rideId, LoadingSheetStatus? status, int page, int pageSize)` — `routeId` filter joins via `Store.FK_RouteId → ShopPO.FK_StoreId → LoadingSheetOrder.FK_ShopPOId` +- `GetByIdAsync(Guid id, bool includeHistory = false)` — `includeHistory = true` includes `IsActive = false` items +- `ReplaceItemsAsync(Guid sheetId, List items)` — soft-delete all current `IsActive = true` rows, insert fresh set +- `ConfirmAsync(Guid id, Guid confirmedBy)` — `Planned → Confirmed`; creates stock movements in transaction + +### `LoadingSheetService.cs` — replace with + +- `PopulateAsync(PopulateRequest request)` — validates ride is `Open`; at least one filter provided; all matching ShopPOs are Confirmed; delegates to repository +- `UpdateItemsAsync(Guid id, UpdateLoadingSheetItemsRequest request)` — validates sheet is `Planned`; calls versioned replace +- `ConfirmAsync(Guid id)` — validates sheet is `Planned`; creates stock movements: one `Load` debit per `LoadingSheetItem.FK_WarehouseId`, one credit to ride's vehicle (`LoadingSheet.FK_RideId → DeliveryRun.FK_VehicleId`); all in one transaction; transitions to `Confirmed` + +### `LoadingSheetController.cs` — replace endpoints + +| Remove | Add | +|---|---| +| `POST /` | `POST /populate` | +| `POST /{id}/confirm-dispatch` | `POST /{id}/confirm` | +| `PUT /{id}/receipt-items` | *(removed)* | +| `POST /{id}/confirm-receipt` | *(removed)* | +| `POST /{id}/resolve` | *(removed)* | +| `PATCH /{id}/dispatch` | *(removed)* | +| `PATCH /{id}/receipt` | *(removed)* | +| `PATCH /{id}/resolve` | *(removed)* | +| `GET /` | `GET /` (add routeId, agentId, shopId filters) | +| `GET /{id}` | `GET /{id}` (add `?history=true`) | +| `PUT /{id}/items` | `PUT /{id}/items` (versioned, Planned only) | + +--- + +## Phase 10 — Overhaul Ride Feature + +See `ride_lifecycle.md` for full state machine. Ride now starts `Open` immediately on creation. + +### `RideDTOs.cs` +```csharp +// Remove: RouteId, SourceWarehouseId, RideType from request and response +record CreateRideRequest(Guid VehicleId, Guid DriverProfileId, int Meterstart); +record RideResponse(Guid Id, Guid VehicleId, Guid DriverProfileId, + RideStatus Status, int Meterstart, int? Meterend, + DateTime? StartedAt, DateTime? ClosedAt, DateTime CreatedAt); +``` + +### `RideService.cs` — replace state machine + +| Remove | Replace with | +|---|---| +| `CreateAsync` (creates Draft) | `CreateAsync` (creates at `Open` directly) | +| `OpenAsync` (Draft → Open) | *(merged into create)* | +| `ActivateAsync` (Open → Active) | *(removed)* | +| `RaiseCancelRequestAsync` | *(removed — no approval flow)* | +| `ApproveCancelAsync` | *(removed)* | +| `RejectCancelAsync` | *(removed)* | +| `GetCancelRequestsAsync` | *(removed)* | +| `GetCancelRequestAsync` | *(removed)* | +| `GetBreakdownAssistAsync` | *(removed)* | +| `CloseAsync` (Active → Closed) | `CloseAsync` (Open → Closed) | +| *(no cancel)* | `CancelAsync` (Open → Cancelled, direct) | + +`AssignDriverAsync` — keep, remove Draft-status guard. + +### `RideController.cs` +Remove endpoints: open, activate, cancel-request, approve-cancel, reject-cancel, breakdown-assist. +Add endpoint: `POST /{id}/cancel`. + +### FK renames in other features +- `Features/DeliveryRide/DeliveryTaskService.cs` — rename `FK_OrderId` → `FK_ShopPOId` references; update Active status guard to `Open` (**note**: full delivery redesign is deferred — minimum change only) +- `Features/Returns/ReturnService.cs` — rename `FK_OrderId` → `FK_ShopPOId` references only (full redesign deferred) + +--- + +## Phase 11 — Program.cs + Config + +### `Program.cs` +```csharp +// Remove +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); // approval flow removed + +// Add +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Update (rename existing registrations) +// IOrderRepository → IShopPORepository (above replaces it) +``` + +### `appsettings.json` / `appsettings.Development.json` +```json +{ + "InvoiceCreationMode": "B" +} +``` + +Read in `ShopPOController` via `IConfiguration` to gate Mode A vs Mode B endpoints. + +--- + +## Phase 12 — Permission Seeding + +Add two permission records (seed migration or data seeder): + +| Code | Description | Role | +|---|---|---| +| `loading.populate` | Trigger loading sheet population; edit items | Dispatcher | +| `loading.confirm` | Confirm loading sheet; commits stock movements | TBD (see Open Items) | + +--- + +## File Change Summary + +### New files +``` +Models/ShopPO.cs +Models/ShopPOItem.cs +Models/Invoice.cs +Models/LoadingSheetOrder.cs +Features/ShopPO/ShopPOController.cs +Features/ShopPO/ShopPOService.cs +Features/ShopPO/IShopPORepository.cs +Features/ShopPO/ShopPORepository.cs +Features/ShopPO/ShopPODTOs.cs +Features/Invoice/InvoiceController.cs +Features/Invoice/InvoiceService.cs +Features/Invoice/IInvoiceRepository.cs +Features/Invoice/InvoiceRepository.cs +Features/Invoice/InvoiceDTOs.cs +``` + +### Deleted files +``` +Models/Sale.cs +Models/Order.cs +Models/OrderItem.cs +Features/Sale/SaleController.cs +Features/Sale/SaleService.cs +Features/Sale/ISaleRepository.cs +Features/Sale/SaleRepository.cs +Features/Sale/SaleDTOs.cs +Features/Order/OrderController.cs +Features/Order/OrderService.cs +Features/Order/IOrderRepository.cs +Features/Order/OrderRepository.cs +Features/Order/OrderDTOs.cs +``` + +### Modified files +``` +Models/Enums.cs +Models/LoadingSheet.cs +Models/LoadingSheetItem.cs +Models/DeliveryRun.cs +Models/Payment.cs +Models/DeliveryTask.cs (FK rename only) +Models/SchemeRedemption.cs (FK rename only) +Models/SaleReturn.cs (FK rename only) +Data/AppDBContext.cs +Features/LoadingEvent/LoadingSheetService.cs +Features/LoadingEvent/LoadingSheetController.cs +Features/LoadingEvent/ILoadingSheetRepository.cs +Features/LoadingEvent/LoadingSheetRepository.cs +Features/LoadingEvent/LoadingSheetDTOs.cs +Features/Payment/PaymentService.cs +Features/Payment/PaymentController.cs +Features/Payment/IPaymentRepository.cs +Features/Payment/PaymentRepository.cs +Features/Payment/PaymentDTOs.cs +Features/Ride/RideService.cs +Features/Ride/RideController.cs +Features/Ride/RideDTOs.cs +Features/DeliveryRide/DeliveryTaskService.cs (FK rename + Active→Open guard) +Features/Returns/ReturnService.cs (FK rename only) +Program.cs +appsettings.json +appsettings.Development.json +``` + +--- + +## Open Items + +### Resolved during implementation + +| # | Item | Resolution | +|---|---|---| +| 2 | Cascade when Confirmed ShopPO is cancelled and Invoice already exists | Cancel is rejected (400) if a linked Invoice exists. Invoice must be voided separately before the ShopPO can be cancelled. No automatic cascade. | +| 3 | Cascade when Confirmed ShopPO is cancelled and it's in a LoadingSheet | Cancel is rejected (400) if the ShopPO appears in any Planned LoadingSheet. Operator must remove it from the sheet first. | +| 4 | `FinalizeInvoiceRequest` payload — free issues field shape | Deferred to a later pass. v1 `POST /api/invoices/{id}/finalize` takes no body and locks the invoice as-is. | +| 5 | Who can confirm a ShopPO? | No role restriction in v1 — any user can confirm. Gating deferred until the auth layer is implemented. | + +### Still open + +| # | Item | Blocks | +|---|---|---| +| 1 | Who holds `loading.confirm` permission? | Permission seeding (`loading.populate`, `loading.confirm`) — explicitly noted as **Pending** in the API reference. Must decide role before seeding. | + +### New items — identified during frontend refactor (2026-09-17) + +| # | Item | Area | +|---|---|---| +| 6 | `order-return-edit-dialog.tsx` — file not verified; client imports it but it was not reviewed during the refactor pass. Needs to be checked for old `orderId`/`OrderResponse` references. | Returns | +| 7 | `sales-visits/` components — any components in this section that interact with sales/orders need auditing against the new ShopPO/Invoice types. | Sales Visits | +| 8 | SysConfig management page not built — the backend has a `SysConfig` model and the `InvoiceCreationMode` config key is read by `ShopPOController`. A UI to view and toggle system config is missing. | Config | +| 9 | InvoiceCreationMode (ModeA vs ModeB) UI branching — the ShopPO confirm button calls `confirm` or `confirmAndCreateInvoice` depending on mode, but the mode is not currently read from the backend. The UI should fetch `GET /api/sys-config` and gate the action accordingly. | Sales / Invoice | +| 10 | Loading Sheet item population UI — `PUT /api/loading-sheets/{id}/items` exists in the API layer but no UI for populating/editing items on a Planned sheet has been built. | Dispatch | +| 11 | `PaymentMethod` enum is missing `Cheque` — per `invoice_collection.md`, the final design includes `Cash`, `Cheque`, `Credit`. The frontend only has `Cash` and `Credit`. Cheque-specific fields (`ChequeNumber`, `ChequeDate`) and `EntryMode` (`RealTime`, `DayEndManual`) are also unimplemented. | Payments | + +--- + +## Deferred (not in this refactor) + +- `SaleReturn` / `CreditNote` — full redesign is a separate pass +- `DeliveryTask` full redesign (Stage 5 — Delivery) — separate pass +- Vehicle stock reconciliation at ride Close/Cancel — separate pass +- Order attachment mechanism for delivery tasks — separate pass diff --git a/Distribution/docs/refactor_docs/ride_lifecycle.md b/Distribution/docs/refactor_docs/ride_lifecycle.md index be99cba..7f64e1d 100644 --- a/Distribution/docs/refactor_docs/ride_lifecycle.md +++ b/Distribution/docs/refactor_docs/ride_lifecycle.md @@ -1,11 +1,36 @@ # [Refactor] Ride Lifecycle — Route-Free, Type-Free Rides -**Status**: Proposed (design only — no code changes yet) +**Status**: Mostly implemented — see [Implementation Status](#implementation-status-2026-09-17) **Refactors**: [../03_ride_lifecycle.md](../03_ride_lifecycle.md) (kept as-is, this is the target design) **Depends On**: 02 — Stock Ledger --- +## Implementation Status (2026-09-17) + +**Done**, verified against `Models/DeliveryRun.cs`, `Features/Ride/*`: +- `RideStatus` collapsed to `Open`/`Cancelled`/`Closed` — no Draft/Active stage anywhere. +- `FK_RouteId`, `RideType`, `ActivatedAt`, `FK_SourceWarehouseId` are all gone from `DeliveryRun`. +- `POST /api/rides` creates directly into `Open` with `StartedAt` set; no `/open`/`/activate` routes. +- `POST /api/rides/{id}/cancel` cancels an `Open` ride directly — no approval step, no + `CancelRequested` stage. +- Driver compliance check (`CheckDriverComplianceAsync`) and the "vehicle can't have two Open rides" + guard are both wired into `RideService.CreateAsync`. +- Dead `RideCancelRequest` model/repository/table removed (2026-09-17) — see Migration Notes. + +**Not done / diverges from this doc:** +1. **`GET /api/rides/breakdown-assist/{rideId}`** — not implemented at all (no route in + `RideController.cs`), not even the trimmed "vehicle stock levels only" version this doc describes. +2. **Impact item 1 (delivery task generation) confirmed still broken, honestly**: + `DeliveryTaskService.GenerateAsync` is a one-line `throw new NotImplementedException("... route- + based dispatch not yet implemented.")` — matches this doc's prediction exactly, not yet designed. +3. **Impact item 4 (stock reconciliation at Close/Cancel without a source warehouse)** — still + unaddressed; `CloseAsync`/`CancelAsync` do not touch `StockBalance` at all. +4. **Impact item 2 (loading sheet auto-population)** — resolved differently than either this doc or + `loading_event.md` predicted; see that document's own Implementation Status section. + +--- + ## Goal Ride should not require a `Route`, should not carry a `RideType`, should not be gated by a warehouse's `Type`, and should not even pin down a source warehouse on the ride record itself. Per direction from the business owner, the ride record carries only what a real dispatch needs to track — **"a ride only carries vehicle, driver assign, and meter reading from start to end."** Everything route-shaped (which stores get visited, which orders/items travel on this trip) and everything warehouse-shaped (where stock loads from/returns to) moves out of the Ride entity's responsibility entirely; neither is replaced by another matching mechanism here. @@ -215,9 +240,10 @@ Not part of this docs-only pass, but captured for the eventual implementation st `DeliveryRun`/`Ride` and their Fluent/EF configuration. `Status` stays, re-typed to the narrowed `RideStatus` (`Open`/`Cancelled`/`Closed`). Add `CancelTypeCode`, `CancelReason`, `CancelledAt` columns to `DeliveryRun`. -- Drop the `RideCancelRequest` table, its Fluent/EF configuration, and - `RideCancelRequestRepository`/`IRideCancelRequestRepository` — the request/approve/reject flow is - gone. +- ~~Drop the `RideCancelRequest` table, its Fluent/EF configuration, and + `RideCancelRequestRepository`/`IRideCancelRequestRepository`~~ — **Done (2026-09-17)**: model, + repository, `DbSet`, and seed data removed; `CancelRequestStatus` enum removed as unused; + migration `RemoveRideCancelRequest` applied, dropping the table. - Remove `RouteId`, `RideType`, and `SourceWarehouseId`/`SourceWarehouseName` from `CreateRideRequest`, `RideResponse`, and `BreakdownAssistRideResponse` in `RideDTOs.cs`. Remove the open-orders list from `BreakdownAssistResponse`. Remove the `RaiseCancelRequest`/cancel-request diff --git a/Distribution/docs/refactor_frontend_api_reference.md b/Distribution/docs/refactor_frontend_api_reference.md new file mode 100644 index 0000000..e7c1042 --- /dev/null +++ b/Distribution/docs/refactor_frontend_api_reference.md @@ -0,0 +1,978 @@ +# Frontend API Reference — ERP Distribution (Post-Refactor) + +> Last updated: 2026-09-17 +> Base URL: `https:///api` +> All responses are JSON. Enum fields are serialized as **strings** (e.g. `"Pending"`, `"ModeB"`). +> All `Guid` fields are UUID v4 strings. All `DateTime` fields are ISO 8601. + +--- + +## Table of Contents + +1. [Pagination](#pagination) +2. [Enums Reference](#enums-reference) +3. [ShopPO](#shoppo) +4. [Invoice](#invoice) +5. [Payment](#payment) +6. [Ride (DeliveryRun)](#ride-deliveryrun) +7. [Loading Sheet](#loading-sheet) +8. [Delivery Tasks](#delivery-tasks) +9. [Returns](#returns) +10. [Schemes](#schemes) +11. [System Config](#system-config) +12. [Key Relationships & Flows](#key-relationships--flows) + +--- + +## Pagination + +All list endpoints return a `PagedResponse`: + +```json +{ + "page": 1, + "pageSize": 20, + "total": 84, + "items": [ /* T[] */ ] +} +``` + +Default page size is `20`. Pass `?page=2&pageSize=50` to paginate. + +--- + +## Enums Reference + +| Enum | Values | +|------|--------| +| `ShopPOStatus` | `Pending`, `PartiallyFulfilled`, `Fulfilled`, `Cancelled` | +| `InvoiceStatus` | `Draft`, `Printed`, `Finalized` | +| `PaymentStatus` | `Pending`, `PartiallyPaid`, `Paid` | +| `PaymentMethod` | `Cash`, `Credit` | +| `RideStatus` | `Open`, `Cancelled`, `Closed` | +| `LoadingSheetStatus` | `Planned`, `Confirmed` | +| `DeliveryTaskStatus` | `Pending`, `Delivered`, `PartiallyDelivered`, `Failed` | +| `ReturnMode` | `CreditDeduction`, `ItemExchange` | +| `ReturnReasonCode` | `Expired`, `Damaged`, `OrderError`, `Other` | +| `CancelRequestType` | `VehicleBreakdown`, `DriverUnavailable`, `RouteIssue`, `Other` | +| `InvoiceCreationMode` | `ModeA`, `ModeB` | +| `SchemeRuleType` | `SlabDiscount`, `FlatPercent`, `BuyXGetY`, `FreeBundle` | + +--- + +## ShopPO + +A ShopPO is a shop-facing purchase order raised by a sales agent on behalf of a store. + +### Status Flow + +``` +Pending → PartiallyFulfilled → Fulfilled + ↘ Cancelled +``` + +### `GET /api/shop-pos` + +List all ShopPOs with optional filters. + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `agentId` | `Guid?` | Filter by the agent who raised the PO | +| `routeId` | `Guid?` | Filter by the store's route | +| `shopId` | `Guid?` | Filter by store | +| `confirmed` | `bool?` | `true` = confirmed only, `false` = unconfirmed only | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "page": 1, + "pageSize": 20, + "total": 12, + "items": [ + { + "id": "uuid", + "storeId": "uuid", + "storeName": "Colombo Mart", + "raisedById": "uuid", + "invoiceId": "uuid | null", + "totalAmount": 15000.00, + "status": "Pending", + "confirmedAt": "2026-09-17T10:00:00 | null", + "confirmedBy": "uuid | null", + "fulfilledAt": "2026-09-17T14:00:00 | null", + "items": [ + { + "id": "uuid", + "itemId": "uuid", + "itemName": "Milo 400g", + "quantity": 10, + "quantityFulfilled": 0, + "unitPrice": 850.00, + "isActive": true + } + ], + "isActive": true, + "createdAt": "2026-09-17T08:00:00" + } + ] +} +``` + +### `GET /api/shop-pos/{id}` + +**Response:** `ShopPOResponse` (same shape as above, single object) or `404`. + +--- + +## Invoice + +An Invoice is the billing document generated from a confirmed ShopPO. There is at most one Invoice per ShopPO. + +**InvoiceCreationMode** (system config) controls whether the invoice is: +- **ModeA** — auto-created when the ShopPO is confirmed +- **ModeB** — created as a separate explicit step (default) + +### Status Flow + +``` +Draft → Printed → Finalized +``` + +Once Finalized, the invoice is locked. Payments can be collected at any status. + +### `GET /api/invoices` + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `agentId` | `Guid?` | Agent who raised the ShopPO | +| `routeId` | `Guid?` | Store's route | +| `shopId` | `Guid?` | Store | +| `status` | `InvoiceStatus?` | `Draft`, `Printed`, `Finalized` | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "page": 1, + "pageSize": 20, + "total": 5, + "items": [ + { + "id": "uuid", + "shopPOId": "uuid", + "storeName": "Colombo Mart", + "status": "Draft", + "paymentStatus": "Pending", + "createdBy": "uuid", + "printedAt": null, + "printedBy": null, + "finalizedAt": null, + "finalizedBy": null, + "totalAmount": 15000.00, + "isActive": true, + "createdAt": "2026-09-17T08:30:00" + } + ] +} +``` + +### `GET /api/invoices/{id}` + +**Response:** `InvoiceResponse` (single) or `404`. + +> **Note:** The detail response from the repository also loads `Payments`. The current `InvoiceResponse` DTO does not yet expose payments — use `GET /api/invoices/{id}/payments` for that. + +--- + +## Payment + +Payments are collected against an Invoice. Multiple payments can be made on one invoice (e.g. partial cash collection). + +### `GET /api/invoices/{invoiceId}/payments` + +Returns all payments for the invoice. + +**Response:** `PaymentResponse[]` + +```json +[ + { + "id": "uuid", + "invoiceId": "uuid", + "amount": 5000.00, + "method": "Cash", + "collectedAt": "2026-09-17T15:00:00", + "collectedBy": "uuid", + "createdAt": "2026-09-17T15:00:00" + } +] +``` + +Returns `404` if the invoice does not exist. + +### `POST /api/invoices/{invoiceId}/payments` + +Record a payment against an invoice. + +**Request body:** + +```json +{ + "amount": 5000.00, + "method": "Cash", + "collectedByUserId": "uuid | null" +} +``` + +| Field | Type | Required | Notes | +|-------|------|----------|-------| +| `amount` | `decimal` | Yes | Must be > 0 | +| `method` | `PaymentMethod` | Yes | `Cash` or `Credit` | +| `collectedByUserId` | `Guid?` | No | Defaults to authenticated user | + +**Response:** `PaymentResponse` or `404` if invoice not found, `400` on business rule violation. + +--- + +## Ride (DeliveryRun) + +A Ride represents a vehicle dispatch for a day. The driver moves along a route making deliveries. + +### Status Flow + +``` +Open → Closed + ↘ Cancelled +``` + +### `GET /api/rides` + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `status` | `RideStatus?` | `Open`, `Cancelled`, `Closed` | +| `driverProfileId` | `Guid?` | Filter by driver | +| `vehicleId` | `Guid?` | Filter by vehicle | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "items": [ + { + "id": "uuid", + "status": "Open", + "vehicleId": "uuid", + "vehicleNumberPlate": "WP CAB 1234", + "driverProfileId": "uuid", + "driverFullName": "Kamal Perera", + "meterstart": 12450, + "meterend": 0, + "startedAt": null, + "closedAt": null, + "createdAt": "2026-09-17T06:00:00" + } + ] +} +``` + +### `GET /api/rides/{id}` + +**Response:** `RideResponse` or `404`. + +### `POST /api/rides` + +Create a new ride. + +**Request body:** + +```json +{ + "vehicleId": "uuid", + "driverProfileId": "uuid", + "meterstart": 12450 +} +``` + +**Response:** `201 Created` with `RideResponse`. `400` on validation error. + +### `PUT /api/rides/{id}/driver` + +Re-assign the driver on an Open ride. + +**Request body:** + +```json +{ + "driverProfileId": "uuid" +} +``` + +**Response:** `RideResponse`. `404` if ride not found. `400` if ride is not Open. + +### `POST /api/rides/{id}/close` + +Close a ride and record the ending odometer. + +**Request body:** + +```json +{ + "meterend": 12890 +} +``` + +**Response:** `RideResponse`. `400` if ride is not Open. + +### `POST /api/rides/{id}/cancel` + +Cancel a ride. + +**Request body:** + +```json +{ + "typeCode": "VehicleBreakdown", + "reason": "Engine overheating" +} +``` + +| Field | Type | Notes | +|-------|------|-------| +| `typeCode` | `CancelRequestType` | `VehicleBreakdown`, `DriverUnavailable`, `RouteIssue`, `Other` | +| `reason` | `string` | Free text reason | + +**Response:** `RideResponse`. `400` if ride is not Open. + +--- + +## Loading Sheet + +A Loading Sheet records the items loaded onto a vehicle before a ride. It belongs to a Ride. + +### Status Flow + +``` +Planned → Confirmed +``` + +Items can only be edited while the sheet is `Planned`. Confirming the sheet commits stock movements (Warehouse → Vehicle). + +### `GET /api/loading-sheets` + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `rideId` | `Guid?` | Filter by ride | +| `status` | `LoadingSheetStatus?` | `Planned`, `Confirmed` | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "items": [ + { + "id": "uuid", + "fK_RideId": "uuid", + "status": "Planned", + "populatedBy": "uuid", + "populatedAt": "2026-09-17T07:00:00", + "confirmedAt": null, + "confirmedBy": null, + "createdAt": "2026-09-17T07:00:00", + "items": [ + { + "id": "uuid", + "fK_ItemId": "uuid", + "itemName": "Milo 400g", + "fK_WarehouseId": "uuid", + "warehouseName": "Colombo Warehouse", + "quantityDispatched": 24.0, + "fK_ShopPOItemId": "uuid | null" + } + ], + "orders": [ + { "shopPOId": "uuid" } + ] + } + ] +} +``` + +### `GET /api/loading-sheets/{id}` + +**Response:** `LoadingSheetResponse` or `404`. + +### `POST /api/loading-sheets` + +Create a new loading sheet for a ride. The ride must exist. Only one `Planned` sheet per ride is allowed. + +**Request body:** + +```json +{ + "fK_RideId": "uuid" +} +``` + +**Response:** `201 Created` with `LoadingSheetResponse`. `400` if ride already has a planned sheet. + +### `PUT /api/loading-sheets/{id}/items` + +Replace all items on a `Planned` loading sheet. This is a full replace — any items not included are removed. + +**Request body:** + +```json +{ + "items": [ + { + "fK_ItemId": "uuid", + "fK_WarehouseId": "uuid", + "quantity": 24.0, + "fK_ShopPOItemId": "uuid | null" + } + ] +} +``` + +| Field | Type | Required | Notes | +|-------|------|----------|-------| +| `fK_ItemId` | `Guid` | Yes | The item being loaded | +| `fK_WarehouseId` | `Guid` | Yes | Source warehouse for this item | +| `quantity` | `decimal` | Yes | Units to load | +| `fK_ShopPOItemId` | `Guid?` | No | Links the load line to a specific ShopPO line item | + +**Response:** `LoadingSheetResponse`. `400` if sheet is not `Planned`. + +### `POST /api/loading-sheets/{id}/confirm` + +Confirm the loading sheet. Commits stock: moves each item from its specified warehouse to the vehicle. Sheet becomes `Confirmed` and can no longer be edited. + +**Request body:** _(none)_ + +**Response:** `LoadingSheetResponse`. `400` if already confirmed. + +--- + +## Delivery Tasks + +Delivery Tasks are the per-stop delivery jobs attached to a Ride. Each task maps to one ShopPO. + +> **Note:** Auto-generation of delivery tasks from route/ShopPO assignments is deferred and not yet implemented. Tasks must be created manually or via a future dispatch endpoint. + +### Status Flow + +``` +Pending → Delivered + ↘ PartiallyDelivered + ↘ Failed +``` + +### `GET /api/rides/{rideId}/tasks` + +List all delivery tasks for a ride, ordered by `Sequence`. + +**Response:** `DeliveryTaskResponse[]` + +```json +[ + { + "id": "uuid", + "fK_RideId": "uuid", + "fK_ShopPOId": "uuid", + "storeId": "uuid", + "storeName": "Galle Mart", + "sequence": 1, + "status": "Pending", + "customerConfirmed": false, + "confirmedAt": null, + "note": null, + "items": [ + { + "itemId": "uuid", + "itemName": "Milo 400g", + "quantity": 10, + "quantityFulfilled": 0, + "unitPrice": 850.00 + } + ], + "createdAt": "2026-09-17T08:00:00" + } +] +``` + +### `GET /api/delivery-tasks/{id}` + +**Response:** `DeliveryTaskResponse` or `404`. + +### `PUT /api/delivery-tasks/{id}/quantities` + +Set the fulfilled quantity for each item in the task. Call this before confirming. + +**Request body:** + +```json +{ + "items": [ + { "itemId": "uuid", "quantityFulfilled": 8 } + ] +} +``` + +**Response:** `DeliveryTaskResponse`. `400` if task is already closed. + +### `POST /api/delivery-tasks/{id}/confirm` + +Mark the task as Delivered or PartiallyDelivered based on quantities set. Updates ShopPO fulfillment, creates stock movement (Vehicle → External), and records payment if applicable. + +**Request body:** _(none)_ + +**Response:** `DeliveryTaskResponse`. `400` if task is not `Pending`. + +### `POST /api/delivery-tasks/{id}/fail` + +Mark the task as Failed with a reason note. + +**Request body:** + +```json +{ + "note": "Store was closed" +} +``` + +**Response:** `DeliveryTaskResponse`. `400` if task is not `Pending`. + +--- + +## Returns + +Returns are recorded against a ShopPO during the same store visit. Effects (credit deduction or item exchange) are applied immediately — no approval step. + +> **Note:** The Create endpoint (`POST /api/shop-pos/{id}/returns`) is currently stubbed (`501 Not Implemented`) while the return flow is being redesigned. `GET` and `PATCH` endpoints are fully operational. + +### `GET /api/returns` + +List all returns. + +**Response:** `SaleReturnResponse[]` + +```json +[ + { + "id": "uuid", + "shopPOId": "uuid", + "mode": "CreditDeduction", + "totalCreditAmount": 1700.00, + "orderTotalAmountAfter": 13300.00, + "isActive": true, + "createdAt": "2026-09-17T11:00:00", + "items": [ + { + "id": "uuid", + "itemId": "uuid", + "sku": "MILO400", + "itemName": "Milo 400g", + "quantity": 2.0, + "reasonCode": "Damaged", + "unitPrice": 850.00 + } + ] + } +] +``` + +### `GET /api/returns/{id}` + +**Response:** `SaleReturnResponse` or `404`. + +### `GET /api/shop-pos/{id}/returns` + +List all returns for a specific ShopPO. + +**Response:** `SaleReturnResponse[]` + +### `POST /api/shop-pos/{id}/returns` + +> **501 Not Implemented** — return flow under redesign. + +**Request body (for future reference):** + +```json +{ + "mode": "CreditDeduction", + "items": [ + { "itemId": "uuid", "quantity": 2.0, "reasonCode": "Damaged" } + ], + "createdByUserId": "uuid" +} +``` + +| `mode` | Effect | +|--------|--------| +| `CreditDeduction` | `totalCreditAmount` is netted off the ShopPO's `TotalAmount` | +| `ItemExchange` | Items are swapped; no monetary credit applied | + +### `PATCH /api/returns/{id}/reasons` + +Update the reason code on individual return line items. Only reason codes can be edited post-creation. + +**Request body:** + +```json +{ + "items": [ + { "itemId": "uuid", "reasonCode": "Expired" } + ] +} +``` + +**Response:** `SaleReturnResponse`. `409` if return is no longer active. + +--- + +## Schemes + +Schemes are promotional rules applied to ShopPOs (formerly Orders). + +### Scheme Rule Types + +| Type | Description | +|------|-------------| +| `SlabDiscount` | Tiered % discount based on order amount. Config: `SlabDiscountConfig` | +| `FlatPercent` | Flat % discount on order total. Config: `FlatPercentConfig` | +| `BuyXGetY` | Buy N of trigger item → get free payout item | +| `FreeBundle` | Buy a bundle of items → get a free payout item | + +### `GET /api/schemes` + +List all schemes (paginated). + +**Response:** `PagedResponse` + +```json +{ + "items": [ + { + "id": "uuid", + "name": "Q3 Volume Boost", + "ruleType": "SlabDiscount", + "ruleConfig": "{\"Tiers\":[{\"MinOrderAmount\":10000,\"DiscountPercent\":5}]}", + "triggerItemId": null, + "triggerItemName": null, + "triggerQty": null, + "freeItemId": null, + "freeItemName": null, + "freeQty": null, + "bundleComponents": [], + "regionId": "uuid | null", + "regionName": "Western Province | null", + "eligibleSegment": null, + "dateRangeFrom": "2026-07-01T00:00:00", + "dateRangeTo": "2026-09-30T00:00:00", + "agentLimitExempt": false, + "baselineExpectedSales": 500000.00, + "isActive": true, + "createdAt": "2026-06-15T09:00:00" + } + ] +} +``` + +### `GET /api/schemes/{id}` + +**Response:** `SchemeResponse` or `404`. + +### `POST /api/schemes` + +Create a scheme. For discount-only schemes (`SlabDiscount`, `FlatPercent`), free-goods fields can be omitted. For `BuyXGetY` / `FreeBundle`, you can supply the free-goods config inline here or set it later via `PUT .../free-goods-rule`. + +**Request body:** + +```json +{ + "name": "Q3 Volume Boost", + "ruleType": "SlabDiscount", + "ruleConfig": "{\"Tiers\":[{\"MinOrderAmount\":10000,\"DiscountPercent\":5}]}", + "regionId": null, + "eligibleSegment": null, + "dateRangeFrom": "2026-07-01T00:00:00", + "dateRangeTo": "2026-09-30T00:00:00", + "agentLimitExempt": false, + "baselineExpectedSales": 500000.00 +} +``` + +#### `ruleConfig` shapes + +**SlabDiscount:** +```json +{ "Tiers": [ { "MinOrderAmount": 10000, "DiscountPercent": 5 }, { "MinOrderAmount": 20000, "DiscountPercent": 8 } ] } +``` + +**FlatPercent:** +```json +{ "DiscountPercent": 3.5 } +``` + +**BuyXGetY / FreeBundle:** `ruleConfig` is `null` — the payout is set via `PUT .../free-goods-rule`. + +### `PUT /api/schemes/{id}` + +Update scheme metadata. Cannot change `ruleType`. + +### `DELETE /api/schemes/{id}` + +Soft-delete (sets `IsActive = false`). + +### `PUT /api/schemes/{id}/free-goods-rule` + +Set the free-goods payout for `BuyXGetY` or `FreeBundle` schemes. + +**Request body:** + +```json +{ + "triggerItemId": "uuid | null", + "triggerQty": 6, + "freeItemId": "uuid", + "freeQty": 1.0 +} +``` + +- `BuyXGetY`: `triggerItemId` + `triggerQty` required (what store must buy). +- `FreeBundle`: `triggerItemId` / `triggerQty` ignored — trigger is the bundle components. + +### `PUT /api/schemes/{id}/bundle-components/{itemId}` + +Add or update a component in a `FreeBundle` scheme. + +**Request body:** + +```json +{ "qty": 4 } +``` + +### `DELETE /api/schemes/{id}/bundle-components/{itemId}` + +Remove a bundle component. + +### `GET /api/shop-pos/{shopPOId}/scheme-eligibility` + +Check which active schemes the ShopPO qualifies for. + +**Response:** `SchemeEligibilityResponse[]` + +```json +[ + { + "schemeId": "uuid", + "schemeName": "Q3 Volume Boost", + "ruleType": "SlabDiscount", + "eligible": true, + "reason": null, + "discountAmount": 750.00, + "freeItemId": null, + "freeQty": null + } +] +``` + +### `POST /api/shop-pos/{shopPOId}/apply-scheme` + +Apply a scheme to the ShopPO (create a redemption record and apply discount/free goods). + +**Request body:** + +```json +{ "schemeId": "uuid" } +``` + +**Response:** `SchemeRedemptionResponse` + +```json +{ + "id": "uuid", + "schemeId": "uuid", + "shopPOId": "uuid", + "discountAmount": 750.00, + "freeItemId": null, + "freeItemName": null, + "freeQty": null, + "freeItemCostValue": null, + "redeemedAt": "2026-09-17T09:30:00" +} +``` + +### `GET /api/schemes/{id}/spend` + +**Response:** `SchemeSpendResponse` + +```json +{ + "schemeId": "uuid", + "totalDiscountSpend": 45000.00, + "totalFreeGoodsCostSpend": 12000.00, + "totalSpend": 57000.00, + "redemptionCount": 38 +} +``` + +### `GET /api/schemes/{id}/roi` + +**Response:** `SchemeROIResponse` + +```json +{ + "schemeId": "uuid", + "baselineExpectedSales": 500000.00, + "actualSales": 620000.00, + "incrementalSales": 120000.00, + "totalSpend": 57000.00, + "roi": 1.105 +} +``` + +--- + +## System Config + +Key-value store for system-wide configuration. All keys and values are strings. Only known keys have typed endpoints with validation. + +### `GET /api/sys-config` + +Return all config entries. + +**Response:** `SysConfigResponse[]` + +```json +[ + { + "key": "InvoiceCreationMode", + "value": "ModeB", + "updatedAt": "2026-09-17T00:00:00", + "updatedBy": null + } +] +``` + +### `GET /api/sys-config/invoice-creation-mode` + +**Response:** + +```json +{ "mode": "ModeB" } +``` + +### `PUT /api/sys-config/invoice-creation-mode` + +**Request body:** + +```json +{ "mode": "ModeA" } +``` + +| Value | Behaviour | +|-------|-----------| +| `ModeA` | Invoice is auto-created when a ShopPO is confirmed | +| `ModeB` | Invoice must be created as a separate explicit step (default) | + +**Response:** `SysConfigResponse`. `400` if value is not a valid `InvoiceCreationMode`. + +### `GET /api/sys-config/{key}` + +Generic getter by key string. `404` if key not set. + +### `PUT /api/sys-config/{key}` + +Generic raw string setter. Requires admin-level auth. + +**Request body:** + +```json +{ "value": "SomeValue" } +``` + +**Response:** `SysConfigResponse`. `400` if value fails validation for a known key. + +--- + +## Key Relationships & Flows + +### Core Entity Chain + +``` +Store ──< ShopPO ──< ShopPOItem + │ + └──► Invoice ──< Payment + │ + └──► SaleReturn ──< SaleReturnItem + │ + └──► SchemeRedemption + +Ride (DeliveryRun) ──► LoadingSheet ──< LoadingSheetItem + └──< DeliveryTask ──► ShopPO +``` + +### ShopPO → Invoice Dependency + +- `ShopPO.invoiceId` is `null` until an invoice is created. +- In **ModeA**, the invoice is created automatically when the ShopPO is confirmed. +- In **ModeB**, the invoice must be created via a dedicated endpoint (not yet exposed — planned). +- An invoice can only exist for a confirmed ShopPO. + +### Payment → Invoice Dependency + +- Payments are always attached to an **Invoice**, never directly to a ShopPO. +- `Invoice.paymentStatus` is computed: + - `Pending` — no payments + - `PartiallyPaid` — payments collected but total < invoice amount + - `Paid` — fully settled + +### Loading Sheet → Stock + +- Confirming a loading sheet deducts each item from its **source warehouse** (`fK_WarehouseId` per line) and credits the **vehicle** stock location. +- Each loading sheet line can optionally link to a `fK_ShopPOItemId` for traceability. + +### Delivery Task → ShopPO Fulfillment + +- Confirming a delivery task updates `ShopPOItem.quantityFulfilled` and transitions the ShopPO status: + - All items fully fulfilled → `Fulfilled` + - Some items partially fulfilled → `PartiallyFulfilled` + +### Returns → ShopPO + +- Returns always reference a `shopPOId`. +- `CreditDeduction` mode: `SaleReturn.totalCreditAmount` is netted off `ShopPO.totalAmount` immediately. +- `ItemExchange` mode: no monetary impact; items are swapped in stock. +- Only the `reasonCode` on each return line can be edited after creation. + +--- + +## What Is Not Yet Implemented + +| Feature | Status | Notes | +|---------|--------|-------| +| ShopPO confirm endpoint | Pending | `PUT /api/shop-pos/{id}/confirm` — triggers InvoiceCreationMode check | +| Invoice create (ModeB) | Pending | `POST /api/invoices` with `{ shopPOId }` | +| Invoice print | Pending | `POST /api/invoices/{id}/print` | +| Invoice finalize | Pending | `POST /api/invoices/{id}/finalize` | +| Delivery task auto-generation | Deferred | Route-based dispatch not yet implemented | +| Returns create | Redesign | `POST /api/shop-pos/{id}/returns` returns `501` | +| Permission seeding | Pending | `loading.populate`, `loading.confirm` scopes | diff --git a/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx b/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx index 64014af..648742d 100644 --- a/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx +++ b/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx @@ -51,7 +51,7 @@ export function DeliveryTasksClient() { const fetchRides = useCallback(async () => { try { - const res = await ridesApi.list({ page: 1, pageSize: 200, rideType: 'Delivery' }) + const res = await ridesApi.list({ page: 1, pageSize: 200 }) const items = getPaginatedItems(res) setRides(items) setSelectedRideId((current) => current || items[0]?.id || '') @@ -188,7 +188,7 @@ export function DeliveryTasksClient() { 0}>Select a ride... {rides.map((ride) => ( - {ride.routeName} - {ride.vehicleNumberPlate} + {ride.vehicleNumberPlate} — {ride.driverFullName} ))} diff --git a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-create-dialog.tsx b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-create-dialog.tsx new file mode 100644 index 0000000..b0031bc --- /dev/null +++ b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-create-dialog.tsx @@ -0,0 +1,113 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useForm, zodResolver, z } from '@/lib/form' +import { FormField } from '@/components/shared/form-field' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from '@/components/ui/dialog' +import { FieldGroup } from '@/components/ui/field' +import { toast } from '@/components/ui/toast' +import { loadingSheets as loadingSheetsApi, rides as ridesApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { RideResponse } from '@/types/api' + +const schema = z.object({ + fK_RideId: z.string().min(1, 'Ride is required'), +}) + +type FormValues = z.infer + +interface LoadingSheetCreateDialogProps { + open: boolean + onClose: () => void + onSuccess: () => void +} + +export function LoadingSheetCreateDialog({ open, onClose, onSuccess }: LoadingSheetCreateDialogProps) { + const [ridesList, setRidesList] = useState([]) + + const form = useForm({ + resolver: zodResolver(schema), + defaultValues: { fK_RideId: '' }, + }) + + useEffect(() => { + if (!open) return + form.reset({ fK_RideId: '' }) + ridesApi.list({ status: 'Open', pageSize: 200 }) + .then((res) => setRidesList(getPaginatedItems(res))) + .catch((err) => toast.add({ title: 'Failed to load rides', description: getApiError(err), type: 'error' })) + }, [open]) + + async function onSubmit(values: FormValues) { + try { + await loadingSheetsApi.create(values) + toast.add({ title: 'Loading sheet created', type: 'success' }) + onSuccess() + onClose() + } catch (err) { + toast.add({ title: 'Failed to create loading sheet', description: getApiError(err), type: 'error' }) + } + } + + return ( + !v && onClose()}> + + + New Loading Sheet + + Create a loading sheet for an open ride. Only one planned sheet per ride is allowed. + + + +
+ + ( + + )} + /> + + + + + + +
+
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx index 8ab855d..227f6ad 100644 --- a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx @@ -11,11 +11,8 @@ import { Separator } from '@/components/ui/separator' import type { LoadingSheetResponse, LoadingSheetStatus } from '@/types/api' const LS_STATUS_VARIANT: Record = { - Pending: 'secondary', - DispatchConfirmed: 'default', - ReceiptConfirmed: 'default', - DiscrepancyFlagged: 'destructive', - Resolved: 'secondary', + Planned: 'secondary', + Confirmed: 'default', } const fmtDateTime = (v: string | null) => @@ -25,6 +22,8 @@ const fmtDateTime = (v: string | null) => }) : '—' +const truncId = (id: string) => id.substring(0, 8) + interface LoadingSheetViewSheetProps { open: boolean onClose: () => void @@ -51,13 +50,12 @@ export function LoadingSheetViewSheet({ open, onClose, sheet }: LoadingSheetView
- {sheet.id.substring(0, 8)}} /> - + {truncId(sheet.id)}} /> + {truncId(sheet.fK_RideId)}} /> {sheet.status}} /> - - - - + + + 0 ? sheet.orders.map(o => truncId(o.shopPOId)).join(', ') : '—'} />
@@ -70,15 +68,14 @@ export function LoadingSheetViewSheet({ open, onClose, sheet }: LoadingSheetView Item - Dispatched - Received - Resolved + Warehouse + Qty {sheet.items.length === 0 ? ( - + No items on this sheet. @@ -86,9 +83,8 @@ export function LoadingSheetViewSheet({ open, onClose, sheet }: LoadingSheetView sheet.items.map((item) => ( {item.itemName} + {item.warehouseName} {item.quantityDispatched} - {item.quantityReceived} - {item.quantityResolved} )) )} diff --git a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx index 36bde8a..25acbc0 100644 --- a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx +++ b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx @@ -1,14 +1,19 @@ 'use client' import { useState, useEffect, useCallback, useMemo } from 'react' +import { HugeiconsIcon } from '@hugeicons/react' +import { Add01Icon } from '@hugeicons/core-free-icons' + import { DataTable } from '@/components/shared/data-table' import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' +import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' import { loadingSheets as loadingSheetsApi, getApiError, getPaginatedItems } from '@/lib/api/index' import type { LoadingSheetResponse, LoadingSheetStatus } from '@/types/api' import { LoadingSheetViewSheet } from './loading-sheet-view-sheet' +import { LoadingSheetCreateDialog } from './loading-sheet-create-dialog' const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) @@ -16,11 +21,8 @@ const fmtDate = (v: string) => const truncId = (id: string) => id.substring(0, 8) const LS_STATUS_VARIANT: Record = { - Pending: 'secondary', - DispatchConfirmed: 'default', - ReceiptConfirmed: 'default', - DiscrepancyFlagged: 'destructive', - Resolved: 'secondary', + Planned: 'secondary', + Confirmed: 'default', } export function LoadingSheetsClient() { @@ -30,6 +32,7 @@ export function LoadingSheetsClient() { const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) + const [createOpen, setCreateOpen] = useState(false) const [viewOpen, setViewOpen] = useState(false) const [selectedSheet, setSelectedSheet] = useState(null) @@ -55,23 +58,13 @@ export function LoadingSheetsClient() { setViewOpen(true) } - async function handleConfirmDispatch(row: LoadingSheetResponse) { + async function handleConfirm(row: LoadingSheetResponse) { try { - await loadingSheetsApi.confirmDispatch(row.id) - toast.add({ title: 'Dispatch confirmed', type: 'success' }) + await loadingSheetsApi.confirm(row.id) + toast.add({ title: 'Loading sheet confirmed — stock committed to vehicle', type: 'success' }) fetchData(page, pageSize) } catch (err) { - toast.add({ title: 'Failed to confirm dispatch', description: getApiError(err), type: 'error' }) - } - } - - async function handleConfirmReceipt(row: LoadingSheetResponse) { - try { - await loadingSheetsApi.confirmReceipt(row.id, []) - toast.add({ title: 'Receipt confirmed', type: 'success' }) - fetchData(page, pageSize) - } catch (err) { - toast.add({ title: 'Failed to confirm receipt', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to confirm loading sheet', description: getApiError(err), type: 'error' }) } } @@ -92,33 +85,45 @@ export function LoadingSheetsClient() { ), }, { - key: 'warehouseName', - title: 'Warehouse', - fields: [{ key: 'warehouseName', primary: true }], - minWidth: 180, + key: 'rideId', + title: 'Ride', + fields: ['fK_RideId'], + width: 140, + cellRender: (row) => ( + {truncId(row.fK_RideId)} + ), }, { key: 'status', title: 'Status', fields: ['status'], - width: 180, + width: 140, cellRender: (row) => ( {row.status} ), }, + { + key: 'orders', + title: 'POs', + fields: ['orders'], + width: 80, + cellRender: (row) => ( + {row.orders.length} + ), + }, { key: 'itemCount', title: 'Items', fields: ['items'], - width: 120, + width: 80, cellRender: (row) => ( - {row.items.length} items + {row.items.length} ), }, { - key: 'createdAt', - title: 'Created', - fields: [{ key: 'createdAt', transform: (v) => fmtDate(v as string) }], + key: 'populatedAt', + title: 'Populated', + fields: [{ key: 'populatedAt', transform: (v) => fmtDate(v as string) }], width: 140, }, ], @@ -131,15 +136,9 @@ export function LoadingSheetsClient() { }, { action: 'confirm', - label: 'Confirm dispatch', - onClick: handleConfirmDispatch, - visible: (target) => target.status === 'Pending', - }, - { - action: 'confirm', - label: 'Confirm receipt', - onClick: handleConfirmReceipt, - visible: (target) => target.status === 'DispatchConfirmed', + label: 'Confirm & commit stock', + onClick: handleConfirm, + visible: (target) => target.status === 'Planned', }, ], }, @@ -151,9 +150,13 @@ export function LoadingSheetsClient() {

Loading Sheets

- Track goods loaded onto a vehicle before dispatch + Items loaded onto a vehicle before a delivery run

+ + setCreateOpen(false)} + onSuccess={() => fetchData(page, pageSize)} + /> + setViewOpen(false)} diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx index 8bfcf52..2a536ee 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx @@ -57,12 +57,12 @@ export function RideCancelDialog({ open, onClose, onSuccess, ride }: RideCancelD async function onSubmit(values: FormValues) { try { - await ridesApi.cancelRequests.raise(ride!.id, values) - toast.add({ title: 'Cancel request raised', type: 'success' }) + await ridesApi.cancel(ride!.id, values) + toast.add({ title: 'Ride cancelled', type: 'success' }) onSuccess() onClose() } catch (err) { - toast.add({ title: 'Failed to raise cancel request', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to cancel ride', description: getApiError(err), type: 'error' }) } } @@ -72,7 +72,7 @@ export function RideCancelDialog({ open, onClose, onSuccess, ride }: RideCancelD Cancel Ride - Raises a cancel request for this ride, subject to supervisor approval. + Cancelling this ride is immediate and cannot be undone. @@ -122,7 +122,7 @@ export function RideCancelDialog({ open, onClose, onSuccess, ride }: RideCancelD Back diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx index 59c1d4f..6c17d8f 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx @@ -72,7 +72,7 @@ export function RideEditDriverSheet({ open, onClose, onSuccess, ride }: RideEdit Edit Ride Driver - Reassign the driver for this ride. Only available while the ride is in Draft status. + Reassign the driver for this ride. Only available while the ride is Open. diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx index 840f79c..bb5412b 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx @@ -26,19 +26,14 @@ import { rides as ridesApi, vehicles as vehiclesApi, drivers as driversApi, - routes as routesApi, - warehouses as warehousesApi, getApiError, getPaginatedItems, } from '@/lib/api/index' -import type { VehicleResponse, DriverProfileResponse, RouteResponse, WarehouseResponse } from '@/types/api' +import type { VehicleResponse, DriverProfileResponse } from '@/types/api' const schema = z.object({ - rideType: z.enum(['Delivery', 'Sale']), vehicleId: z.string().min(1, 'Vehicle is required'), driverProfileId: z.string().min(1, 'Driver is required'), - routeId: z.string().min(1, 'Route is required'), - sourceWarehouseId: z.string().min(1, 'Warehouse is required'), meterstart: z.number().min(0, 'Meter start must be 0 or more'), }) @@ -50,21 +45,15 @@ interface RideSheetProps { onSuccess: () => void } - export function RideSheet({ open, onClose, onSuccess }: RideSheetProps) { const [vehiclesList, setVehiclesList] = useState([]) const [driversList, setDriversList] = useState([]) - const [routesList, setRoutesList] = useState([]) - const [warehousesList, setWarehousesList] = useState([]) const form = useForm({ resolver: zodResolver(schema), defaultValues: { - rideType: 'Delivery', vehicleId: '', driverProfileId: '', - routeId: '', - sourceWarehouseId: '', meterstart: 0, }, }) @@ -73,26 +62,18 @@ export function RideSheet({ open, onClose, onSuccess }: RideSheetProps) { if (!open) return form.reset({ - rideType: 'Delivery', vehicleId: '', driverProfileId: '', - routeId: '', - sourceWarehouseId: '', meterstart: 0, }) - // available=true tells backend to exclude vehicles already on an open ride Promise.all([ vehiclesApi.list({ available: true, isActive: true, pageSize: 200 }), driversApi.list({ pageSize: 200 }), - routesApi.list({ pageSize: 200 }), - warehousesApi.list({ pageSize: 200 }), ]) - .then(([v, d, r, w]) => { + .then(([v, d]) => { setVehiclesList(getPaginatedItems(v)) setDriversList(getPaginatedItems(d)) - setRoutesList(getPaginatedItems(r)) - setWarehousesList(getPaginatedItems(w)) }) .catch((err) => { toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' }) @@ -115,30 +96,11 @@ export function RideSheet({ open, onClose, onSuccess }: RideSheetProps) { Create Ride - Start a new delivery or sales run. + Start a new delivery run for a driver and vehicle.
- ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - = { - Draft: 'secondary', - Open: 'secondary', - Active: 'default', - CancelRequested: 'destructive', + Open: 'default', Cancelled: 'destructive', Closed: 'secondary', } -const RIDE_TYPE_VARIANT: Record = { - Delivery: 'default', - Sale: 'secondary', -} - const fmtDateTime = (v: string | null) => v ? new Date(v).toLocaleString('en-GB', { @@ -58,14 +50,10 @@ export function RideViewSheet({ open, onClose, ride }: RideViewSheetProps) {
- - - {ride.rideType}} /> {ride.status}} /> - - + + -
diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx index 8e58ea2..0fe1f35 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx @@ -10,7 +10,7 @@ import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' import { rides as ridesApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { RideResponse, RideStatus, RideType } from '@/types/api' +import type { RideResponse, RideStatus } from '@/types/api' import { RideSheet } from './ride-sheet' import { RideViewSheet } from './ride-view-sheet' @@ -22,19 +22,11 @@ const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) const RIDE_STATUS_VARIANT: Record = { - Draft: 'secondary', - Open: 'secondary', - Active: 'default', - CancelRequested: 'destructive', + Open: 'default', Cancelled: 'destructive', Closed: 'secondary', } -const RIDE_TYPE_VARIANT: Record = { - Delivery: 'default', - Sale: 'secondary', -} - export function RidesClient() { const [data, setData] = useState([]) const [loading, setLoading] = useState(true) @@ -81,16 +73,6 @@ export function RidesClient() { setCancelOpen(true) } - async function handleActivate(row: RideResponse) { - try { - await ridesApi.activate(row.id) - toast.add({ title: 'Ride activated', type: 'success' }) - fetchData(page, pageSize) - } catch (err) { - toast.add({ title: 'Failed to activate ride', description: getApiError(err), type: 'error' }) - } - } - function handleClose(row: RideResponse) { setSelectedRide(row) setCloseOpen(true) @@ -115,30 +97,29 @@ export function RidesClient() { ), }, - { - key: 'routeName', - title: 'Route', - fields: [{ key: 'routeName', primary: true }], - minWidth: 160, - }, - { - key: 'rideType', - title: 'Type', - fields: ['rideType'], - width: 120, - cellRender: (row) => ( - {row.rideType} - ), - }, { key: 'status', title: 'Status', fields: ['status'], - width: 160, + width: 140, cellRender: (row) => ( {row.status} ), }, + { + key: 'meter', + title: 'Meter', + fields: ['meterstart', 'meterend'], + width: 160, + cellRender: (row) => ( +
+

{row.meterstart} km

+ {row.meterend ? ( +

→ {row.meterend} km

+ ) : null} +
+ ), + }, { key: 'createdAt', title: 'Created', @@ -157,25 +138,19 @@ export function RidesClient() { action: 'edit', label: 'Edit driver', onClick: handleEditDriver, - visible: (target) => target.status === 'Draft', - }, - { - action: 'activate', - label: 'Activate ride', - onClick: handleActivate, visible: (target) => target.status === 'Open', }, { action: 'close', label: 'Close ride', onClick: handleClose, - visible: (target) => target.status === 'Active', + visible: (target) => target.status === 'Open', }, { action: 'cancel', label: 'Cancel ride', onClick: handleCancel, - visible: (target) => target.status === 'Active', + visible: (target) => target.status === 'Open', }, ], }, @@ -192,7 +167,7 @@ export function RidesClient() { diff --git a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx index 05bfb64..b1693bd 100644 --- a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx +++ b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx @@ -27,14 +27,13 @@ import { HugeiconsIcon } from '@hugeicons/react' import { Add01Icon, Delete02Icon } from '@hugeicons/core-free-icons' import { saleReturns as saleReturnsApi, - orders as ordersApi, - stores as storesApi, + shopPos as shopPosApi, items as itemsApi, users as usersApi, getApiError, getPaginatedItems, } from '@/lib/api/index' -import type { OrderResponse, ItemSummaryResponse, UserResponse, ReturnReasonCode } from '@/types/api' +import type { ShopPOResponse, ItemSummaryResponse, UserResponse, ReturnReasonCode } from '@/types/api' const REASON_CODES: ReturnReasonCode[] = ['Expired', 'Damaged', 'OrderError', 'Other'] @@ -45,7 +44,7 @@ const returnItemSchema = z.object({ }) const schema = z.object({ - orderId: z.string().min(1, 'Order is required'), + shopPOId: z.string().min(1, 'Shop PO is required'), mode: z.enum(['CreditDeduction', 'ItemExchange']), createdByUserId: z.string().min(1, 'Created by is required'), items: z.array(returnItemSchema).min(1, 'At least one item is required'), @@ -64,58 +63,55 @@ function defaultItem() { } export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialogProps) { - const [ordersList, setOrdersList] = useState([]) - const [storeNameById, setStoreNameById] = useState>(new Map()) + const [shopPOList, setShopPOList] = useState([]) const [itemsList, setItemsList] = useState([]) const [usersList, setUsersList] = useState([]) - const [selectedOrder, setSelectedOrder] = useState(null) + const [selectedPO, setSelectedPO] = useState(null) const form = useForm({ resolver: zodResolver(schema), - defaultValues: { orderId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }, + defaultValues: { shopPOId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }, }) const { fields, append, remove } = useFieldArray({ control: form.control, name: 'items' }) const itemsById = useMemo(() => new Map(itemsList.map((i) => [i.id, i])), [itemsList]) - const eligibleOrders = useMemo( - () => ordersList.filter((o) => o.status !== 'Cancelled' && o.status !== 'Fulfilled'), - [ordersList] + const eligiblePOs = useMemo( + () => shopPOList.filter((o) => o.status !== 'Cancelled' && o.confirmedAt), + [shopPOList] ) useEffect(() => { if (!open) return - form.reset({ orderId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }) - setSelectedOrder(null) + form.reset({ shopPOId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }) + setSelectedPO(null) Promise.all([ - ordersApi.list(), - storesApi.list({ pageSize: 200 }), + shopPosApi.list({ pageSize: 200 }), itemsApi.list({ pageSize: 200 }), usersApi.list({ pageSize: 200 }), ]) - .then(([orderList, storeList, itemsRes, usersRes]) => { - setOrdersList(orderList) - setStoreNameById(new Map(getPaginatedItems(storeList).map((s) => [s.id, s.storeName]))) + .then(([posRes, itemsRes, usersRes]) => { + setShopPOList(getPaginatedItems(posRes)) setItemsList(getPaginatedItems(itemsRes)) setUsersList(getPaginatedItems(usersRes)) }) .catch((err) => toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' })) }, [open]) - function handleOrderChange(orderId: string | null) { - form.setValue('orderId', orderId ?? '', { shouldValidate: true }) - const order = orderId ? ordersList.find((o) => o.id === orderId) ?? null : null - setSelectedOrder(order) + function handlePOChange(shopPOId: string | null) { + form.setValue('shopPOId', shopPOId ?? '', { shouldValidate: true }) + const po = shopPOId ? shopPOList.find((o) => o.id === shopPOId) ?? null : null + setSelectedPO(po) } async function onSubmit(values: FormValues) { try { - await saleReturnsApi.create(values.orderId, { + await saleReturnsApi.create(values.shopPOId, { mode: values.mode, items: values.items, createdByUserId: values.createdByUserId, }) - toast.add({ title: 'Order return recorded', type: 'success' }) + toast.add({ title: 'Return recorded', type: 'success' }) onSuccess() onClose() } catch (err) { @@ -123,14 +119,15 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo } } + const activeItems = selectedPO?.items.filter((i) => i.isActive) ?? [] + return ( { if (!v) onClose() }}> Record Order Return - Record items a store returned against an open order. Only items the store has previously - ordered can be returned. + Record items a store returned against a confirmed Shop PO. @@ -138,19 +135,19 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo ( - - + - Select order... - {eligibleOrders.map((o) => ( + Select Shop PO... + {eligiblePOs.map((o) => ( - {storeNameById.get(o.storeId) ?? o.storeId.slice(0, 8)} — {o.id.slice(0, 8).toUpperCase()} ({o.status}) + {o.storeName} — {o.id.slice(0, 8).toUpperCase()} ({o.status}) ))} @@ -200,7 +197,7 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo - {selectedOrder && ( + {selectedPO && (

Items to Return

@@ -223,11 +220,11 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo Select item... - {selectedOrder.items.map((oi) => { + {activeItems.map((oi) => { const item = itemsById.get(oi.itemId) return ( - {item?.name ?? oi.itemId.slice(0, 8)} {item ? `— ${item.sku}` : ''} + {oi.itemName}{item ? ` — ${item.sku}` : ''} ) })} @@ -282,7 +279,7 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo - diff --git a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx index 4ba1660..8997cc3 100644 --- a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx @@ -49,7 +49,7 @@ export function OrderReturnViewSheet({ open, onClose, ret, storeName }: OrderRet
{storeName && } - {ret.orderId}} /> + {ret.shopPOId}} /> {MODE_LABEL[ret.mode]}} /> diff --git a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx index d11ff3d..5d28ec0 100644 --- a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx +++ b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx @@ -9,7 +9,7 @@ import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' -import { saleReturns as saleReturnsApi, orders as ordersApi, stores as storesApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import { saleReturns as saleReturnsApi, shopPos as shopPosApi, stores as storesApi, getApiError, getPaginatedItems } from '@/lib/api/index' import type { SaleReturnResponse, ReturnMode } from '@/types/api' import { OrderReturnViewSheet } from './order-return-view-sheet' import { OrderReturnDialog } from './order-return-dialog' @@ -49,13 +49,13 @@ export function OrderReturnsClient() { const fetchData = useCallback(async () => { setLoading(true) try { - const [returns, orderList, storeList] = await Promise.all([ + const [returns, shopPOList, storeList] = await Promise.all([ saleReturnsApi.list(), - ordersApi.list(), + shopPosApi.list({ pageSize: 200 }), storesApi.list({ pageSize: 200 }), ]) const storeNameById = new Map(getPaginatedItems(storeList).map((s) => [s.id, s.storeName])) - const map = new Map(orderList.map((o) => [o.id, storeNameById.get(o.storeId) ?? '—'])) + const map = new Map(getPaginatedItems(shopPOList).map((o) => [o.id, storeNameById.get(o.storeId) ?? o.storeName])) setStoreNameByOrderId(map) setData(returns) } catch (err) { @@ -78,10 +78,10 @@ export function OrderReturnsClient() { { key: 'store', title: 'Store', - fields: ['orderId'], + fields: ['shopPOId'], minWidth: 200, cellRender: (row) => ( - {storeNameByOrderId.get(row.orderId) ?? '—'} + {storeNameByOrderId.get(row.shopPOId) ?? '—'} ), }, { @@ -163,7 +163,7 @@ export function OrderReturnsClient() { open={viewOpen} onClose={() => setViewOpen(false)} ret={viewing} - storeName={viewing ? storeNameByOrderId.get(viewing.orderId) : undefined} + storeName={viewing ? storeNameByOrderId.get(viewing.shopPOId) : undefined} /> = { - Pending: 'secondary', - Completed: 'default', - Cancelled: 'destructive', -} - -const PAYMENT_STATUS_VARIANT: Record = { - Pending: 'secondary', - PartiallyPaid: 'secondary', - Paid: 'default', -} - -const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` -const truncId = (id: string) => id.substring(0, 8) - -const fmtDateTime = (v: string | null) => - v - ? new Date(v).toLocaleString('en-GB', { - day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', - }) - : '—' - -interface SaleViewSheetProps { - open: boolean - onClose: () => void - sale: SaleResponse | null -} - -function Row({ label, value }: { label: string; value: React.ReactNode }) { - return ( -
- {label} - {value} -
- ) -} - -export function SaleViewSheet({ open, onClose, sale }: SaleViewSheetProps) { - if (!sale) return null - - return ( - !v && onClose()}> - - - Sale Details - - -
- {truncId(sale.id)}} /> - {truncId(sale.storeId)}} /> - {sale.status}} /> - {sale.paymentStatus}} /> - - - - - - -
- - - -
-

Items ({sale.items.length})

-
- - - - - - - - - - - {sale.items.length === 0 ? ( - - - - ) : ( - sale.items.map((item) => ( - - - - - - - )) - )} - -
ItemQuantityFulfilledUnit Price
- No items on this sale. -
{truncId(item.itemId)}{item.quantity}{item.quantityFulfilled}{fmtAmount(item.unitPrice)}
-
-
-
-
- ) -} +// Replaced by shop-po-view-sheet.tsx +export {} diff --git a/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx b/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx index 4f9c997..bb02cd2 100644 --- a/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx @@ -1,7 +1,6 @@ 'use client' import { useState, useEffect, useCallback, useMemo } from 'react' -import { useRouter } from 'next/navigation' import { HugeiconsIcon } from '@hugeicons/react' import { Add01Icon } from '@hugeicons/core-free-icons' @@ -10,10 +9,11 @@ import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' -import { sales as salesApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { SaleResponse, SaleStatus, PaymentStatus } from '@/types/api' +import { shopPos as shopPosApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { ShopPOResponse, ShopPOStatus } from '@/types/api' -import { SaleViewSheet } from './sale-view-sheet' +import { ShopPOViewSheet } from './shop-po-view-sheet' +import { ShopPOCreateSheet } from './shop-po-create-sheet' const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) @@ -21,36 +21,31 @@ const fmtDate = (v: string) => const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -const SALE_STATUS_VARIANT: Record = { +const PO_STATUS_VARIANT: Record = { Pending: 'secondary', - Completed: 'default', + PartiallyFulfilled: 'secondary', + Fulfilled: 'default', Cancelled: 'destructive', } -const PAYMENT_STATUS_VARIANT: Record = { - Pending: 'secondary', - PartiallyPaid: 'secondary', - Paid: 'default', -} - export function SalesClient() { - const router = useRouter() - const [data, setData] = useState([]) + const [data, setData] = useState([]) const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) const [viewOpen, setViewOpen] = useState(false) - const [selectedSale, setSelectedSale] = useState(null) + const [createOpen, setCreateOpen] = useState(false) + const [selectedPO, setSelectedPO] = useState(null) const fetchData = useCallback(async (p: number, ps: number) => { setLoading(true) try { - const res = await salesApi.list({ page: p, pageSize: ps }) + const res = await shopPosApi.list({ page: p, pageSize: ps }) setData(getPaginatedItems(res)) setTotal(res.total) } catch (err) { - toast.add({ title: 'Failed to load sales', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to load Shop POs', description: getApiError(err), type: 'error' }) } finally { setLoading(false) } @@ -60,45 +55,52 @@ export function SalesClient() { fetchData(page, pageSize) }, [fetchData, page, pageSize]) - function handleView(row: SaleResponse) { - setSelectedSale(row) + function handleView(row: ShopPOResponse) { + setSelectedPO(row) setViewOpen(true) } - async function handleCancel(row: SaleResponse) { + async function handleConfirm(row: ShopPOResponse) { try { - await salesApi.cancel(row.id) - toast.add({ title: 'Sale cancelled', type: 'success' }) + await shopPosApi.confirm(row.id) + toast.add({ title: 'Shop PO confirmed', type: 'success' }) fetchData(page, pageSize) } catch (err) { - toast.add({ title: 'Failed to cancel sale', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to confirm Shop PO', description: getApiError(err), type: 'error' }) } } - const tableConfig = useMemo>(() => ({ + async function handleCancel(row: ShopPOResponse) { + try { + await shopPosApi.cancel(row.id) + toast.add({ title: 'Shop PO cancelled', type: 'success' }) + fetchData(page, pageSize) + } catch (err) { + toast.add({ title: 'Failed to cancel Shop PO', description: getApiError(err), type: 'error' }) + } + } + + const tableConfig = useMemo>(() => ({ rowKey: 'id', serverSide: true, stickyHeader: true, - emptyMessage: 'No sales found.', + emptyMessage: 'No Shop POs found.', pagination: { enabled: true, pageSize, pageSizeOptions: [10, 20, 50] }, columns: [ { key: 'id', - title: 'Sale ID', + title: 'PO ID', fields: ['id'], - width: 140, + width: 120, cellRender: (row) => ( {truncId(row.id)} ), }, { - key: 'storeId', - title: 'Store ID', - fields: ['storeId'], - width: 140, - cellRender: (row) => ( - {truncId(row.storeId)} - ), + key: 'store', + title: 'Store', + fields: [{ key: 'storeName', primary: true }], + minWidth: 180, }, { key: 'totalAmount', @@ -113,25 +115,21 @@ export function SalesClient() { key: 'status', title: 'Status', fields: ['status'], - width: 140, - cellRender: (row) => ( - {row.status} - ), - }, - { - key: 'paymentStatus', - title: 'Payment', - fields: ['paymentStatus'], width: 160, cellRender: (row) => ( - {row.paymentStatus} + {row.status} ), }, { - key: 'saleDate', - title: 'Sale Date', - fields: [{ key: 'saleDate', transform: (v) => fmtDate(v as string) }], - width: 140, + key: 'confirmed', + title: 'Confirmed', + fields: ['confirmedAt'], + width: 120, + cellRender: (row) => ( + + {row.confirmedAt ? fmtDate(row.confirmedAt) : 'Unconfirmed'} + + ), }, { key: 'createdAt', @@ -144,14 +142,20 @@ export function SalesClient() { actions: () => [ { action: 'view', - label: 'View sale', + label: 'View PO', onClick: handleView, }, + { + action: 'confirm', + label: 'Confirm PO', + onClick: handleConfirm, + visible: (target) => !target.confirmedAt && target.status !== 'Cancelled', + }, { action: 'cancel', - label: 'Cancel sale', + label: 'Cancel PO', onClick: handleCancel, - visible: (target) => target.status !== 'Cancelled', + visible: (target) => target.status !== 'Cancelled' && target.status !== 'Fulfilled', }, ], }, @@ -161,14 +165,14 @@ export function SalesClient() { <>
-

Sales

+

Shop POs

- Sales transactions recorded against stores + Purchase orders raised by agents on behalf of stores

-
@@ -183,10 +187,16 @@ export function SalesClient() { }} /> - setCreateOpen(false)} + onSuccess={() => fetchData(page, pageSize)} + /> + + setViewOpen(false)} - sale={selectedSale} + po={selectedPO} /> ) diff --git a/distribution_fe/app/(dashboard)/sales/_components/shop-po-create-sheet.tsx b/distribution_fe/app/(dashboard)/sales/_components/shop-po-create-sheet.tsx new file mode 100644 index 0000000..0fdad1d --- /dev/null +++ b/distribution_fe/app/(dashboard)/sales/_components/shop-po-create-sheet.tsx @@ -0,0 +1,217 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useForm, zodResolver, z } from '@/lib/form' +import { FormField } from '@/components/shared/form-field' +import { Input } from '@/components/ui/input' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from '@/components/ui/dialog' +import { FieldGroup } from '@/components/ui/field' +import { toast } from '@/components/ui/toast' +import { shopPos as shopPosApi, stores as storesApi, items as itemsApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { StoreResponse, ItemSummaryResponse } from '@/types/api' + +const itemLineSchema = z.object({ + itemId: z.string().min(1, 'Item required'), + quantity: z.number().int().min(1, 'Min 1'), + unitPrice: z.number().min(0, 'Price must be 0 or more'), +}) + +const schema = z.object({ + storeId: z.string().min(1, 'Store is required'), + items: z.array(itemLineSchema).min(1, 'At least one item is required'), +}) + +type FormValues = z.infer + +interface ShopPOCreateSheetProps { + open: boolean + onClose: () => void + onSuccess: () => void +} + +const emptyLine = { itemId: '', quantity: 1, unitPrice: 0 } + +export function ShopPOCreateSheet({ open, onClose, onSuccess }: ShopPOCreateSheetProps) { + const [storesList, setStoresList] = useState([]) + const [itemsList, setItemsList] = useState([]) + + const form = useForm({ + resolver: zodResolver(schema), + defaultValues: { storeId: '', items: [emptyLine] }, + }) + + const watchedItems = form.watch('items') + + useEffect(() => { + if (!open) return + form.reset({ storeId: '', items: [emptyLine] }) + Promise.all([ + storesApi.list({ pageSize: 200 }), + itemsApi.list({ pageSize: 200 }), + ]) + .then(([s, i]) => { + setStoresList(getPaginatedItems(s)) + setItemsList(getPaginatedItems(i)) + }) + .catch((err) => toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' })) + }, [open]) + + function addLine() { + form.setValue('items', [...watchedItems, emptyLine]) + } + + function removeLine(idx: number) { + form.setValue('items', watchedItems.filter((_, i) => i !== idx)) + } + + async function onSubmit(values: FormValues) { + try { + await shopPosApi.create(values) + toast.add({ title: 'Shop PO created', type: 'success' }) + onSuccess() + onClose() + } catch (err) { + toast.add({ title: 'Failed to create Shop PO', description: getApiError(err), type: 'error' }) + } + } + + return ( + !v && onClose()}> + + + New Shop PO + Raise a purchase order on behalf of a store. + + + + + ( + + )} + /> + + +
+
+

Line Items

+ +
+ +
+ {watchedItems.map((_, idx) => ( +
+ ( + + )} + /> + ( + field.onChange(Number(e.target.value))} + onBlur={field.onBlur} + aria-invalid={invalid} + /> + )} + /> + ( + field.onChange(Number(e.target.value))} + onBlur={field.onBlur} + aria-invalid={invalid} + /> + )} + /> +
+ +
+
+ ))} +
+
+ + + + + + +
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/sales/_components/shop-po-view-sheet.tsx b/distribution_fe/app/(dashboard)/sales/_components/shop-po-view-sheet.tsx new file mode 100644 index 0000000..911233c --- /dev/null +++ b/distribution_fe/app/(dashboard)/sales/_components/shop-po-view-sheet.tsx @@ -0,0 +1,106 @@ +'use client' + +import { Badge } from '@/components/ui/badge' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' +import { Separator } from '@/components/ui/separator' +import type { ShopPOResponse, ShopPOStatus } from '@/types/api' + +const PO_STATUS_VARIANT: Record = { + Pending: 'secondary', + PartiallyFulfilled: 'secondary', + Fulfilled: 'default', + Cancelled: 'destructive', +} + +const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` +const truncId = (id: string) => id.substring(0, 8) + +const fmtDateTime = (v: string | null) => + v + ? new Date(v).toLocaleString('en-GB', { + day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', + }) + : '—' + +interface ShopPOViewSheetProps { + open: boolean + onClose: () => void + po: ShopPOResponse | null +} + +function Row({ label, value }: { label: string; value: React.ReactNode }) { + return ( +
+ {label} + {value} +
+ ) +} + +export function ShopPOViewSheet({ open, onClose, po }: ShopPOViewSheetProps) { + if (!po) return null + + return ( + !v && onClose()}> + + + Shop PO Details + + +
+ {truncId(po.id)}} /> + + {po.status}} /> + + {truncId(po.invoiceId)} : 'No invoice yet'} /> + + + +
+ + + +
+

Line Items ({po.items.filter(i => i.isActive).length})

+
+ + + + + + + + + + + + {po.items.filter(i => i.isActive).length === 0 ? ( + + + + ) : ( + po.items.filter(i => i.isActive).map((item) => ( + + + + + + + + )) + )} + +
ItemQtyFulfilledUnit PriceLine Total
+ No items on this PO. +
{item.itemName}{item.quantity}{item.quantityFulfilled}{fmtAmount(item.unitPrice)}{fmtAmount(item.quantity * item.unitPrice)}
+
+
+
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/sales/new/page.tsx b/distribution_fe/app/(dashboard)/sales/new/page.tsx index 6d04845..d384969 100644 --- a/distribution_fe/app/(dashboard)/sales/new/page.tsx +++ b/distribution_fe/app/(dashboard)/sales/new/page.tsx @@ -15,24 +15,21 @@ import { SelectTrigger, SelectValue, } from '@/components/ui/select' -import { Checkbox } from '@/components/ui/checkbox' import { Button } from '@/components/ui/button' import { FieldGroup } from '@/components/ui/field' import { Separator } from '@/components/ui/separator' import { toast } from '@/components/ui/toast' import { - sales as salesApi, + shopPos as shopPosApi, stores as storesApi, - rides as ridesApi, items as itemsApi, - users as usersApi, priceLists as priceListsApi, getApiError, getPaginatedItems, } from '@/lib/api/index' -import type { ItemSummaryResponse, RideResponse, StoreResponse, UserResponse } from '@/types/api' +import type { ItemSummaryResponse, StoreResponse } from '@/types/api' -const saleItemSchema = z.object({ +const lineItemSchema = z.object({ itemId: z.string().min(1, 'Item is required'), quantity: z.number().min(1, 'Quantity must be at least 1'), unitPrice: z.number().min(0.01, 'Unit price must be greater than 0'), @@ -40,11 +37,7 @@ const saleItemSchema = z.object({ const schema = z.object({ storeId: z.string().min(1, 'Store is required'), - saleDate: z.string().min(1, 'Sale date is required'), - createdByUserId: z.string().min(1, 'Created by is required'), - rideId: z.string(), - fulfillImmediately: z.boolean(), - items: z.array(saleItemSchema).min(1, 'At least one item is required'), + items: z.array(lineItemSchema).min(1, 'At least one item is required'), }) type FormValues = z.infer @@ -53,61 +46,46 @@ function createDefaultItem() { return { itemId: '', quantity: 1, unitPrice: 0 } } -function todayIso() { - return new Date().toISOString().slice(0, 10) -} - const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` -export default function NewSalePage() { +export default function NewShopPOPage() { const router = useRouter() const [storesList, setStoresList] = useState([]) - const [ridesList, setRidesList] = useState([]) const [itemsList, setItemsList] = useState([]) - const [usersList, setUsersList] = useState([]) + const [priceMinByIndex, setPriceMinByIndex] = useState>({}) + const [priceRetailByIndex, setPriceRetailByIndex] = useState>({}) const form = useForm({ resolver: zodResolver(schema), - defaultValues: { - storeId: '', - saleDate: todayIso(), - createdByUserId: '', - rideId: '', - fulfillImmediately: false, - items: [createDefaultItem()], - }, - }) - - const { fields, append, remove } = useFieldArray({ - control: form.control, - name: 'items', + defaultValues: { storeId: '', items: [createDefaultItem()] }, }) + const { fields, append, remove } = useFieldArray({ control: form.control, name: 'items' }) const watchedItems = useWatch({ control: form.control, name: 'items' }) const watchedStoreId = useWatch({ control: form.control, name: 'storeId' }) - const watchedSaleDate = useWatch({ control: form.control, name: 'saleDate' }) + const itemsById = useMemo( () => new Map(itemsList.map((item) => [item.id, item])), [itemsList] ) + const totalAmount = useMemo( - () => watchedItems.reduce((sum, item) => sum + (Number(item.quantity) || 0) * (Number(item.unitPrice) || 0), 0), + () => watchedItems.reduce((sum, line) => sum + (Number(line.quantity) || 0) * (Number(line.unitPrice) || 0), 0), [watchedItems] ) - const [priceMinByIndex, setPriceMinByIndex] = useState>({}) - const [priceRetailByIndex, setPriceRetailByIndex] = useState>({}) async function resolveAndSetPrice(index: number, itemId: string) { const item = itemsById.get(itemId) - if (watchedStoreId && watchedSaleDate) { + const today = new Date().toISOString().slice(0, 10) + if (watchedStoreId) { try { - const resolution = await priceListsApi.resolve({ itemId, storeId: watchedStoreId, saleDate: watchedSaleDate }) + const resolution = await priceListsApi.resolve({ itemId, storeId: watchedStoreId, saleDate: today }) form.setValue(`items.${index}.unitPrice`, resolution.price, { shouldValidate: true }) setPriceMinByIndex((prev) => ({ ...prev, [index]: resolution.minPrice })) setPriceRetailByIndex((prev) => ({ ...prev, [index]: resolution.retailPrice })) return } catch { - // No resolvable price for this store/date (e.g. store/item not found) — fall back below. + // No resolvable price for this store — fall back to item default. } } if (item) { @@ -117,28 +95,22 @@ export default function NewSalePage() { } } - // Re-resolve every already-selected line's price whenever the store or sale date changes, - // since the applicable price list is scoped by the store's region and the sale date. useEffect(() => { - if (!watchedStoreId || !watchedSaleDate) return + if (!watchedStoreId) return watchedItems.forEach((line, index) => { if (line.itemId) resolveAndSetPrice(index, line.itemId) }) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [watchedStoreId, watchedSaleDate]) + }, [watchedStoreId]) useEffect(() => { Promise.all([ storesApi.list({ pageSize: 200 }), - ridesApi.list({ pageSize: 200, rideType: 'Sale' }), itemsApi.list({ pageSize: 200 }), - usersApi.list({ pageSize: 200 }), ]) - .then(([stores, rides, items, usersRes]) => { + .then(([stores, items]) => { setStoresList(getPaginatedItems(stores)) - setRidesList(getPaginatedItems(rides)) setItemsList(getPaginatedItems(items)) - setUsersList(getPaginatedItems(usersRes)) }) .catch((err) => { toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' }) @@ -147,18 +119,14 @@ export default function NewSalePage() { async function onSubmit(values: FormValues) { try { - await salesApi.create({ + await shopPosApi.create({ storeId: values.storeId, - saleDate: values.saleDate, - rideId: values.rideId || null, - fulfillImmediately: values.fulfillImmediately, items: values.items, - createdByUserId: values.createdByUserId, }) - toast.add({ title: 'Sale created', type: 'success' }) + toast.add({ title: 'Shop PO created', type: 'success' }) router.push('/sales') } catch (err) { - toast.add({ title: 'Failed to create sale', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to create Shop PO', description: getApiError(err), type: 'error' }) } } @@ -170,116 +138,34 @@ export default function NewSalePage() { Back
-

Create Sale

-

Record a sale for a store with one or more items.

+

Create Shop PO

+

Record a purchase order for a store.

-

Sale Details

+

Order Details

-
- ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> -
- ( - + )} />
@@ -313,7 +199,9 @@ export default function NewSalePage() { {fields.map((fieldItem, index) => { const selectedItem = itemsById.get(watchedItems[index]?.itemId ?? '') - const lineTotal = (Number(watchedItems[index]?.quantity) || 0) * (Number(watchedItems[index]?.unitPrice) || 0) + const lineTotal = + (Number(watchedItems[index]?.quantity) || 0) * + (Number(watchedItems[index]?.unitPrice) || 0) return ( @@ -336,7 +224,7 @@ export default function NewSalePage() { Select item... {itemsList.map((item) => ( - {item.name} - {item.sku} + {item.name} — {item.sku} ))} @@ -356,9 +244,6 @@ export default function NewSalePage() { name={`items.${index}.quantity`} render={({ field, invalid }) => ( ( {priceMinByIndex[index] != null && (

- Negotiable down to {fmtAmount(priceMinByIndex[index]!)} + Min: {fmtAmount(priceMinByIndex[index]!)}

)} {priceRetailByIndex[index] != null && (

- Retail price: {fmtAmount(priceRetailByIndex[index]!)} + Retail: {fmtAmount(priceRetailByIndex[index]!)}

)} @@ -426,9 +308,9 @@ export default function NewSalePage() {
-

Sale Summary

+

Order Summary

- {watchedItems.length} item{watchedItems.length === 1 ? '' : 's'} on this sale. + {watchedItems.length} item{watchedItems.length === 1 ? '' : 's'} on this order.

@@ -440,7 +322,7 @@ export default function NewSalePage() {
- - - - -
- ) -} +// Retained for compatibility — invoice status transitions are now handled inline via table row actions. +export {} diff --git a/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx b/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx index ab2a68d..3a82da6 100644 --- a/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx @@ -7,14 +7,18 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog' -import { Separator } from '@/components/ui/separator' -import type { OrderResponse, OrderStatus } from '@/types/api' +import type { InvoiceResponse, InvoiceStatus, PaymentStatus } from '@/types/api' -const ORDER_STATUS_VARIANT: Record = { +const INVOICE_STATUS_VARIANT: Record = { + Draft: 'secondary', + Printed: 'secondary', + Finalized: 'default', +} + +const PAYMENT_STATUS_VARIANT: Record = { Pending: 'secondary', - PartiallyFulfilled: 'secondary', - Fulfilled: 'default', - Cancelled: 'destructive', + PartiallyPaid: 'secondary', + Paid: 'default', } const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` @@ -30,8 +34,7 @@ const fmtDateTime = (v: string | null) => interface OrderViewSheetProps { open: boolean onClose: () => void - order: OrderResponse | null - storeName?: string + invoice: InvoiceResponse | null } function Row({ label, value }: { label: string; value: React.ReactNode }) { @@ -43,61 +46,26 @@ function Row({ label, value }: { label: string; value: React.ReactNode }) { ) } -export function OrderViewSheet({ open, onClose, order, storeName }: OrderViewSheetProps) { - if (!order) return null +export function OrderViewSheet({ open, onClose, invoice }: OrderViewSheetProps) { + if (!invoice) return null return ( !v && onClose()}> - + - Order Details + Invoice Details
- {truncId(order.id)}} /> - {truncId(order.saleId)}} /> - {truncId(order.storeId)}} /> - {order.status}} /> - - - - -
- - - -
-

Items ({order.items.length})

-
- - - - - - - - - - - {order.items.length === 0 ? ( - - - - ) : ( - order.items.map((item) => ( - - - - - - - )) - )} - -
ItemQuantityFulfilledUnit Price
- No items on this order. -
{truncId(item.itemId)}{item.quantity}{item.quantityFulfilled}{fmtAmount(item.unitPrice)}
-
+ {truncId(invoice.id)}} /> + {truncId(invoice.shopPOId)}} /> + + {invoice.status}} /> + {invoice.paymentStatus}} /> + + + +
diff --git a/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx b/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx index 6499008..980a219 100644 --- a/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx @@ -6,11 +6,10 @@ import { DataTable } from '@/components/shared/data-table' import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { toast } from '@/components/ui/toast' -import { orders as ordersApi, stores as storesApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { OrderResponse, OrderStatus, StoreResponse } from '@/types/api' +import { invoices as invoicesApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { InvoiceResponse, InvoiceStatus, PaymentStatus } from '@/types/api' import { OrderViewSheet } from './order-view-sheet' -import { OrderEditStatusDialog } from './order-edit-status-dialog' const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) @@ -18,78 +17,80 @@ const fmtDate = (v: string) => const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -const ORDER_STATUS_VARIANT: Record = { +const INVOICE_STATUS_VARIANT: Record = { + Draft: 'secondary', + Printed: 'secondary', + Finalized: 'default', +} + +const PAYMENT_STATUS_VARIANT: Record = { Pending: 'secondary', - PartiallyFulfilled: 'secondary', - Fulfilled: 'default', - Cancelled: 'destructive', + PartiallyPaid: 'secondary', + Paid: 'default', } export function OrdersClient() { - const [data, setData] = useState([]) + const [data, setData] = useState([]) const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) + const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) const [viewOpen, setViewOpen] = useState(false) - const [editOpen, setEditOpen] = useState(false) - const [selectedOrder, setSelectedOrder] = useState(null) - const [storesList, setStoresList] = useState([]) + const [selectedInvoice, setSelectedInvoice] = useState(null) - const storesById = useMemo( - () => new Map(storesList.map((s) => [s.id, s.storeName])), - [storesList] - ) - - const fetchData = useCallback(async () => { + const fetchData = useCallback(async (p: number, ps: number) => { setLoading(true) try { - const items = await ordersApi.list() - setData(items) - setTotal(items.length) + const res = await invoicesApi.list({ page: p, pageSize: ps }) + setData(getPaginatedItems(res)) + setTotal(res.total) } catch (err) { - toast.add({ title: 'Failed to load orders', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to load invoices', description: getApiError(err), type: 'error' }) } finally { setLoading(false) } }, []) useEffect(() => { - fetchData() - storesApi.list({ pageSize: 200 }) - .then((res) => setStoresList(getPaginatedItems(res))) - .catch((err) => toast.add({ title: 'Failed to load stores', description: getApiError(err), type: 'error' })) - }, [fetchData]) + fetchData(page, pageSize) + }, [fetchData, page, pageSize]) - function handleView(row: OrderResponse) { - setSelectedOrder(row) + function handleView(row: InvoiceResponse) { + setSelectedInvoice(row) setViewOpen(true) } - function handleEdit(row: OrderResponse) { - setSelectedOrder(row) - setEditOpen(true) - } - - async function handleDelete(row: OrderResponse) { + async function handlePrint(row: InvoiceResponse) { try { - await ordersApi.delete(row.id) - toast.add({ title: 'Order cancelled', type: 'success' }) - fetchData() + await invoicesApi.print(row.id) + toast.add({ title: 'Invoice marked as printed', type: 'success' }) + fetchData(page, pageSize) } catch (err) { - toast.add({ title: 'Failed to cancel order', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to print invoice', description: getApiError(err), type: 'error' }) } } - const tableConfig = useMemo>(() => ({ + async function handleFinalize(row: InvoiceResponse) { + try { + await invoicesApi.finalize(row.id) + toast.add({ title: 'Invoice finalized', type: 'success' }) + fetchData(page, pageSize) + } catch (err) { + toast.add({ title: 'Failed to finalize invoice', description: getApiError(err), type: 'error' }) + } + } + + const tableConfig = useMemo>(() => ({ rowKey: 'id', + serverSide: true, stickyHeader: true, - emptyMessage: 'No orders found.', + emptyMessage: 'No invoices found.', pagination: { enabled: true, pageSize, pageSizeOptions: [10, 20, 50] }, columns: [ { key: 'id', - title: 'Order ID', + title: 'Invoice ID', fields: ['id'], width: 140, cellRender: (row) => ( @@ -97,22 +98,10 @@ export function OrdersClient() { ), }, { - key: 'saleId', - title: 'Sale ID', - fields: ['saleId'], - width: 140, - cellRender: (row) => ( - {truncId(row.saleId)} - ), - }, - { - key: 'storeId', + key: 'store', title: 'Store', - fields: ['storeId'], - minWidth: 160, - cellRender: (row) => ( - {storesById.get(row.storeId) ?? truncId(row.storeId)} - ), + fields: [{ key: 'storeName', primary: true }], + minWidth: 180, }, { key: 'totalAmount', @@ -127,16 +116,19 @@ export function OrdersClient() { key: 'status', title: 'Status', fields: ['status'], - width: 180, + width: 140, cellRender: (row) => ( - {row.status} + {row.status} ), }, { - key: 'orderDate', - title: 'Order Date', - fields: [{ key: 'orderDate', transform: (v) => fmtDate(v as string) }], - width: 140, + key: 'paymentStatus', + title: 'Payment', + fields: ['paymentStatus'], + width: 150, + cellRender: (row) => ( + {row.paymentStatus} + ), }, { key: 'createdAt', @@ -149,32 +141,32 @@ export function OrdersClient() { actions: () => [ { action: 'view', - label: 'View order', + label: 'View invoice', onClick: handleView, }, { - action: 'edit', - label: 'Edit status', - onClick: handleEdit, - visible: (target) => target.status !== 'Cancelled', + action: 'print', + label: 'Mark as printed', + onClick: handlePrint, + visible: (target) => target.status === 'Draft', }, { - action: 'cancel', - label: 'Delete order', - onClick: handleDelete, - visible: (target) => target.status !== 'Cancelled', + action: 'finalize', + label: 'Finalize invoice', + onClick: handleFinalize, + visible: (target) => target.status === 'Printed', }, ], }, - }), [pageSize, storesById]) + }), [pageSize]) return ( <>
-

Orders

+

Invoices

- Fulfillment status of store orders + Billing documents generated from confirmed Shop POs

@@ -185,6 +177,7 @@ export function OrdersClient() { loading={loading} totalCount={total} onServerSideChange={({ page: p }) => { + setPage(p.page) setPageSize(p.pageSize) }} /> @@ -192,15 +185,7 @@ export function OrdersClient() { setViewOpen(false)} - order={selectedOrder} - storeName={selectedOrder ? storesById.get(selectedOrder.storeId) : undefined} - /> - - setEditOpen(false)} - onSuccess={fetchData} - order={selectedOrder} + invoice={selectedInvoice} /> ) diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx index 28e945f..0878203 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx @@ -1,6 +1,6 @@ 'use client' -import { useEffect, useState } from 'react' +import { useEffect } from 'react' import { useForm, zodResolver, z } from '@/lib/form' import { FormField } from '@/components/shared/form-field' import { Input } from '@/components/ui/input' @@ -11,6 +11,7 @@ import { SelectTrigger, SelectValue, } from '@/components/ui/select' +import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group' import { Button } from '@/components/ui/button' import { Dialog, @@ -22,15 +23,26 @@ import { } from '@/components/ui/dialog' import { FieldGroup } from '@/components/ui/field' import { toast } from '@/components/ui/toast' -import { payments as paymentsApi, sales as salesApi, users as usersApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { SaleResponse, UserResponse } from '@/types/api' +import { payments as paymentsApi, getApiError } from '@/lib/api/index' +import type { InvoiceResponse } from '@/types/api' -const schema = z.object({ - saleId: z.string().min(1, 'Sale is required'), - amount: z.number().min(0.01, 'Amount must be greater than 0'), - method: z.enum(['Cash', 'Credit']), - collectedByUserId: z.string().min(1, 'Collected by is required'), -}) +const schema = z + .object({ + invoiceId: z.string().min(1, 'Invoice is required'), + amount: z.number().min(0.01, 'Amount must be greater than 0'), + method: z.enum(['Cash', 'Cheque', 'Credit']), + entryMode: z.enum(['RealTime', 'DayEndManual']), + chequeNumber: z.string().optional(), + chequeDate: z.string().optional(), + }) + .refine((data) => data.method !== 'Cheque' || !!data.chequeNumber, { + message: 'Cheque number is required for cheque payments', + path: ['chequeNumber'], + }) + .refine((data) => data.method !== 'Cheque' || !!data.chequeDate, { + message: 'Cheque date is required for cheque payments', + path: ['chequeDate'], + }) type FormValues = z.infer @@ -38,51 +50,48 @@ interface PaymentSheetProps { open: boolean onClose: () => void onSuccess: () => void + invoices: InvoiceResponse[] } const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -export function PaymentSheet({ open, onClose, onSuccess }: PaymentSheetProps) { - const [salesList, setSalesList] = useState([]) - const [usersList, setUsersList] = useState([]) - +export function PaymentSheet({ open, onClose, onSuccess, invoices }: PaymentSheetProps) { const form = useForm({ resolver: zodResolver(schema), defaultValues: { - saleId: '', + invoiceId: '', amount: 0, method: 'Cash', - collectedByUserId: '', + entryMode: 'RealTime', + chequeNumber: '', + chequeDate: '', }, }) + const method = form.watch('method') + useEffect(() => { if (!open) return - form.reset({ - saleId: '', + invoiceId: '', amount: 0, method: 'Cash', - collectedByUserId: '', + entryMode: 'RealTime', + chequeNumber: '', + chequeDate: '', }) - - Promise.all([ - salesApi.list({ pageSize: 200 }), - usersApi.list({ pageSize: 200 }), - ]) - .then(([salesRes, usersRes]) => { - setSalesList(getPaginatedItems(salesRes).filter((s) => s.status !== 'Cancelled')) - setUsersList(getPaginatedItems(usersRes)) - }) - .catch((err) => { - toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' }) - }) }, [open]) async function onSubmit(values: FormValues) { + const { invoiceId, method, chequeNumber, chequeDate, ...rest } = values try { - await paymentsApi.create(values) + await paymentsApi.create(invoiceId, { + ...rest, + method, + chequeNumber: method === 'Cheque' ? chequeNumber : undefined, + chequeDate: method === 'Cheque' ? chequeDate : undefined, + }) toast.add({ title: 'Payment recorded', type: 'success' }) onSuccess() onClose() @@ -91,31 +100,33 @@ export function PaymentSheet({ open, onClose, onSuccess }: PaymentSheetProps) { } } + const pendingInvoices = invoices.filter((inv) => inv.paymentStatus !== 'Paid') + return ( !v && onClose()}> Record Payment - Record a cash or credit payment against a sale. + Record a cash, cheque, or credit payment against an invoice.
( + )} /> + {method === 'Cheque' && ( + <> + ( + + )} + /> + + ( + + )} + /> + + )} + ( - + value[0] && field.onChange(value[0])} + > + Real-time + Day-end entry + )} /> diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx index 1468570..bc00bd1 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx @@ -7,13 +7,19 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog' -import type { PaymentResponse, PaymentMethod } from '@/types/api' +import type { PaymentResponse, PaymentMethod, EntryMode } from '@/types/api' -const PAYMENT_METHOD_VARIANT: Record = { +const PAYMENT_METHOD_VARIANT: Record = { Cash: 'default', + Cheque: 'outline', Credit: 'secondary', } +const ENTRY_MODE_LABEL: Record = { + RealTime: 'Real-time', + DayEndManual: 'Day-end entry', +} + const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) @@ -22,12 +28,14 @@ const fmtDateTime = (v: string) => day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', }) +const fmtDate = (v: string) => + new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) + interface PaymentViewSheetProps { open: boolean onClose: () => void payment: PaymentResponse | null - storeName?: string - collectedByName?: string + invoiceName?: string } function Row({ label, value }: { label: string; value: React.ReactNode }) { @@ -39,7 +47,7 @@ function Row({ label, value }: { label: string; value: React.ReactNode }) { ) } -export function PaymentViewSheet({ open, onClose, payment, storeName, collectedByName }: PaymentViewSheetProps) { +export function PaymentViewSheet({ open, onClose, payment, invoiceName }: PaymentViewSheetProps) { if (!payment) return null return ( @@ -51,12 +59,21 @@ export function PaymentViewSheet({ open, onClose, payment, storeName, collectedB
{truncId(payment.id)}} /> - {truncId(payment.saleId)}} /> - {truncId(payment.storeId)}} /> + {truncId(payment.invoiceId)}} /> {payment.method}} /> + {payment.method === 'Cheque' && ( + <> + + + + )} + {ENTRY_MODE_LABEL[payment.entryMode]}} /> - {truncId(payment.collectedBy)}} /> + {truncId(payment.collectedBy)}} /> + {payment.recordedBy && ( + {truncId(payment.recordedBy)}} /> + )}
diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx index 8327b16..daef14a 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx @@ -8,9 +8,10 @@ import { DataTable } from '@/components/shared/data-table' import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' import { toast } from '@/components/ui/toast' -import { payments as paymentsApi, stores as storesApi, users as usersApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { PaymentResponse, PaymentMethod, StoreResponse, UserResponse } from '@/types/api' +import { invoices as invoicesApi, payments as paymentsApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { PaymentResponse, PaymentMethod, EntryMode, InvoiceResponse } from '@/types/api' import { PaymentSheet } from './payment-sheet' import { PaymentViewSheet } from './payment-view-sheet' @@ -21,39 +22,51 @@ const fmtDate = (v: string) => const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -const PAYMENT_METHOD_VARIANT: Record = { +const PAYMENT_METHOD_VARIANT: Record = { Cash: 'default', + Cheque: 'outline', Credit: 'secondary', } +const ENTRY_MODE_LABEL: Record = { + RealTime: 'Real-time', + DayEndManual: 'Day-end entry', +} + export function PaymentsClient() { + const [invoicesList, setInvoicesList] = useState([]) + const [selectedInvoiceId, setSelectedInvoiceId] = useState('') const [data, setData] = useState([]) - const [loading, setLoading] = useState(true) + const [loading, setLoading] = useState(false) const [total, setTotal] = useState(0) - const [page, setPage] = useState(1) - const [pageSize, setPageSize] = useState(20) + const [pageSize] = useState(20) const [sheetOpen, setSheetOpen] = useState(false) const [viewOpen, setViewOpen] = useState(false) const [selectedPayment, setSelectedPayment] = useState(null) - const [storesList, setStoresList] = useState([]) - const [usersList, setUsersList] = useState([]) - const storeNameById = useMemo( - () => new Map(storesList.map((s) => [s.id, s.storeName])), - [storesList] - ) - const userNameById = useMemo( - () => new Map(usersList.map((u) => [u.id, u.fullName])), - [usersList] + const invoiceNameById = useMemo( + () => new Map(invoicesList.map((inv) => [inv.id, `${inv.storeName} — ${truncId(inv.id)}`])), + [invoicesList] ) - const fetchData = useCallback(async (p: number, ps: number) => { + useEffect(() => { + invoicesApi.list({ pageSize: 200 }) + .then((res) => setInvoicesList(getPaginatedItems(res))) + .catch((err) => toast.add({ title: 'Failed to load invoices', description: getApiError(err), type: 'error' })) + }, []) + + const fetchData = useCallback(async (invoiceId: string) => { + if (!invoiceId) { + setData([]) + setTotal(0) + return + } setLoading(true) try { - const res = await paymentsApi.list({ page: p, pageSize: ps }) - setData(getPaginatedItems(res)) - setTotal(res.total) + const items = await paymentsApi.listByInvoice(invoiceId) + setData(items) + setTotal(items.length) } catch (err) { toast.add({ title: 'Failed to load payments', description: getApiError(err), type: 'error' }) } finally { @@ -62,17 +75,8 @@ export function PaymentsClient() { }, []) useEffect(() => { - fetchData(page, pageSize) - }, [fetchData, page, pageSize]) - - useEffect(() => { - storesApi.list({ pageSize: 200 }) - .then((res) => setStoresList(getPaginatedItems(res))) - .catch((err) => toast.add({ title: 'Failed to load stores', description: getApiError(err), type: 'error' })) - usersApi.list({ pageSize: 200 }) - .then((res) => setUsersList(getPaginatedItems(res))) - .catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' })) - }, []) + fetchData(selectedInvoiceId) + }, [fetchData, selectedInvoiceId]) function handleView(row: PaymentResponse) { setSelectedPayment(row) @@ -81,9 +85,8 @@ export function PaymentsClient() { const tableConfig = useMemo>(() => ({ rowKey: 'id', - serverSide: true, stickyHeader: true, - emptyMessage: 'No payments found.', + emptyMessage: selectedInvoiceId ? 'No payments found for this invoice.' : 'Enter an invoice ID to view its payments.', pagination: { enabled: true, pageSize, pageSizeOptions: [10, 20, 50] }, columns: [ { @@ -96,12 +99,12 @@ export function PaymentsClient() { ), }, { - key: 'storeId', - title: 'Store', - fields: ['storeId'], - minWidth: 160, + key: 'invoiceId', + title: 'Invoice', + fields: ['invoiceId'], + minWidth: 180, cellRender: (row) => ( - {storeNameById.get(row.storeId) ?? truncId(row.storeId)} + {invoiceNameById.get(row.invoiceId) ?? truncId(row.invoiceId)} ), }, { @@ -122,21 +125,21 @@ export function PaymentsClient() { {row.method} ), }, + { + key: 'entryMode', + title: 'Entry Mode', + fields: ['entryMode'], + width: 130, + cellRender: (row) => ( + {ENTRY_MODE_LABEL[row.entryMode]} + ), + }, { key: 'collectedAt', title: 'Collected At', fields: [{ key: 'collectedAt', transform: (v) => fmtDate(v as string) }], width: 140, }, - { - key: 'collectedBy', - title: 'Collected By', - fields: ['collectedBy'], - minWidth: 160, - cellRender: (row) => ( - {userNameById.get(row.collectedBy) ?? truncId(row.collectedBy)} - ), - }, ], rowActions: { actions: () => [ @@ -147,7 +150,7 @@ export function PaymentsClient() { }, ], }, - }), [pageSize, storeNameById, userNameById]) + }), [pageSize, invoiceNameById]) return ( <> @@ -155,7 +158,7 @@ export function PaymentsClient() {

Payments

- Cash and credit payments collected from stores + Cash, cheque, and credit payments collected against invoices

+
+ setSelectedInvoiceId(e.target.value.trim())} + /> + {selectedInvoiceId && ( + + )} +
+ { - setPage(p.page) - setPageSize(p.pageSize) - }} /> setSheetOpen(false)} - onSuccess={() => fetchData(page, pageSize)} + onSuccess={() => fetchData(selectedInvoiceId)} + invoices={invoicesList} /> setViewOpen(false)} payment={selectedPayment} - storeName={selectedPayment ? storeNameById.get(selectedPayment.storeId) : undefined} - collectedByName={selectedPayment ? userNameById.get(selectedPayment.collectedBy) : undefined} + invoiceName={selectedPayment ? invoiceNameById.get(selectedPayment.invoiceId) : undefined} /> ) diff --git a/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx b/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx index 467aeaf..420b278 100644 --- a/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx +++ b/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx @@ -50,7 +50,7 @@ type FormValues = z.infer interface StoreSheetProps { open: boolean onClose: () => void - store: StoreResponse + store: StoreResponse | null onSuccess: () => void } @@ -81,7 +81,7 @@ export function StoreSheet({ open, onClose, store, onSuccess }: StoreSheetProps) toast.add({ title: 'Failed to load routes', description: getApiError(err), type: 'error' }) ) - form.reset({ + if (store) form.reset({ storeName: store.storeName, ownerName: store.ownerName, storeAddress: store.storeAddress, @@ -97,7 +97,7 @@ export function StoreSheet({ open, onClose, store, onSuccess }: StoreSheetProps) async function onSubmit(values: FormValues) { try { - await storesApi.update(store.id, { + await storesApi.update(store!.id, { ...values, segment: values.segment || undefined, }) diff --git a/distribution_fe/components/shared/data-table/types.ts b/distribution_fe/components/shared/data-table/types.ts index 47cac6c..e7e6708 100644 --- a/distribution_fe/components/shared/data-table/types.ts +++ b/distribution_fe/components/shared/data-table/types.ts @@ -10,7 +10,9 @@ export type RowActionKind = | 'deactivate' | 'confirm' | 'close' - | 'cancel'; + | 'cancel' + | 'print' + | 'finalize'; export interface BadgeConfig { colorMap?: Record; diff --git a/distribution_fe/components/shared/row-actions.tsx b/distribution_fe/components/shared/row-actions.tsx index 01037d9..05b6487 100644 --- a/distribution_fe/components/shared/row-actions.tsx +++ b/distribution_fe/components/shared/row-actions.tsx @@ -5,9 +5,11 @@ import { HugeiconsIcon } from "@hugeicons/react" import { Cancel01Icon, CheckmarkCircle02Icon, + CheckmarkSquare01Icon, Delete02Icon, EyeIcon, PencilEdit01Icon, + PrinterIcon, } from "@hugeicons/core-free-icons" import { Button } from "@/components/ui/button" @@ -20,6 +22,8 @@ const ACTION_ICONS = { confirm: CheckmarkCircle02Icon, deactivate: Cancel01Icon, edit: PencilEdit01Icon, + finalize: CheckmarkSquare01Icon, + print: PrinterIcon, view: EyeIcon, } as const diff --git a/distribution_fe/components/ui/toggle-group.tsx b/distribution_fe/components/ui/toggle-group.tsx new file mode 100644 index 0000000..b85eb1a --- /dev/null +++ b/distribution_fe/components/ui/toggle-group.tsx @@ -0,0 +1,89 @@ +"use client" + +import * as React from "react" +import { Toggle as TogglePrimitive } from "@base-ui/react/toggle" +import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group" +import { type VariantProps } from "class-variance-authority" +import { cn } from "cn" + +import { toggleVariants } from "@/components/ui/toggle" + +const ToggleGroupContext = React.createContext< + VariantProps & { + spacing?: number + orientation?: "horizontal" | "vertical" + } +>({ + size: "default", + variant: "default", + spacing: 2, + orientation: "horizontal", +}) + +function ToggleGroup({ + className, + variant, + size, + spacing = 2, + orientation = "horizontal", + children, + ...props +}: ToggleGroupPrimitive.Props & + VariantProps & { + spacing?: number + orientation?: "horizontal" | "vertical" + }) { + return ( + + + {children} + + + ) +} + +function ToggleGroupItem({ + className, + children, + variant = "default", + size = "default", + ...props +}: TogglePrimitive.Props & VariantProps) { + const context = React.useContext(ToggleGroupContext) + + return ( + + {children} + + ) +} + +export { ToggleGroup, ToggleGroupItem } diff --git a/distribution_fe/components/ui/toggle.tsx b/distribution_fe/components/ui/toggle.tsx new file mode 100644 index 0000000..d6f4977 --- /dev/null +++ b/distribution_fe/components/ui/toggle.tsx @@ -0,0 +1,44 @@ +"use client" + +import { Toggle as TogglePrimitive } from "@base-ui/react/toggle" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "cn" + +const toggleVariants = cva( + "group/toggle inline-flex items-center justify-center gap-1 rounded-2xl text-sm font-medium whitespace-nowrap transition-colors outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/30 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + { + variants: { + variant: { + default: "bg-transparent", + outline: "border border-input bg-transparent hover:bg-muted", + }, + size: { + default: + "h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", + sm: "h-7 min-w-7 px-2.5 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5", + lg: "h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Toggle({ + className, + variant = "default", + size = "default", + ...props +}: TogglePrimitive.Props & VariantProps) { + return ( + + ) +} + +export { Toggle, toggleVariants } diff --git a/distribution_fe/config/nav.ts b/distribution_fe/config/nav.ts index 315219c..fa863d2 100644 --- a/distribution_fe/config/nav.ts +++ b/distribution_fe/config/nav.ts @@ -60,12 +60,12 @@ export const NAV_GROUPS: NavGroup[] = [ ], }, { - title: 'Sales & Orders', + title: 'Shop POs & Invoices', icon: DollarSquareIcon, items: [ - { title: 'Sales', href: '/sales', icon: DollarSquareIcon, description: 'Sales transactions recorded against stores', permission: 'orders.view' }, - { title: 'Orders', href: '/sales/orders', icon: ClipboardListIcon, description: 'Fulfillment status of store orders', permission: 'orders.view' }, - { title: 'Payments', href: '/sales/payments', icon: BankIcon, description: 'Cash and credit payments collected from stores', permission: 'orders.view' }, + { title: 'Shop POs', href: '/sales', icon: ClipboardListIcon, description: 'Purchase orders raised by sales agents on behalf of stores', permission: 'orders.view' }, + { title: 'Invoices', href: '/sales/orders', icon: DollarSquareIcon, description: 'Billing documents generated from confirmed Shop POs', permission: 'orders.view' }, + { title: 'Payments', href: '/sales/payments', icon: BankIcon, description: 'Cash and credit payments collected against invoices', permission: 'orders.view' }, ], }, { @@ -161,6 +161,6 @@ export const BOTTOM_NAV_CANDIDATES: NavItem[] = [ { title: 'Stores', href: '/stores', icon: Store01Icon, permission: 'stores.view' }, { title: 'Rides', href: '/operations/rides', icon: TruckIcon, permission: 'rides.view' }, { title: 'Loading', href: '/operations/loading', icon: DeliveryBox01Icon, permission: 'loading.view' }, - { title: 'Sales', href: '/sales', icon: DollarSquareIcon, permission: 'orders.view' }, + { title: 'Shop POs', href: '/sales', icon: ClipboardListIcon, permission: 'orders.view' }, { title: 'Items', href: '/catalogue/items', icon: Package01Icon, permission: 'items.view' }, ] diff --git a/distribution_fe/lib/api/index.ts b/distribution_fe/lib/api/index.ts index 8b6a06b..65c81eb 100644 --- a/distribution_fe/lib/api/index.ts +++ b/distribution_fe/lib/api/index.ts @@ -8,7 +8,7 @@ export { drivers, compliance } from './drivers' export { purchaseOrders, grn, purchaseReturns } from './procurement' export { rides, loadingSheets, deliveryTasks } from './operations' export { stock } from './stock' -export { sales, orders, payments } from './sales' +export { shopPos, invoices, payments } from './sales' export { saleReturns, claims, supplierClaims } from './returns-claims' export { getPaginatedItems } from './paginated' diff --git a/distribution_fe/lib/api/operations.ts b/distribution_fe/lib/api/operations.ts index 00d6a62..7abd22f 100644 --- a/distribution_fe/lib/api/operations.ts +++ b/distribution_fe/lib/api/operations.ts @@ -2,10 +2,8 @@ import { api } from '@/lib/api' import type { PaginatedResponse, RideResponse, - CancelRequestResponse, LoadingSheetResponse, DeliveryTaskResponse, - RideType, RideStatus, CancelRequestType, LoadingSheetStatus, @@ -16,22 +14,18 @@ import type { PageParams } from './master' // ─── Rides ──────────────────────────────────────────────────────────────────── export interface RideBody { - rideType: RideType vehicleId: string driverProfileId: string - routeId: string - sourceWarehouseId: string meterstart: number } export interface RideListParams extends PageParams { status?: RideStatus - rideType?: RideType driverProfileId?: string vehicleId?: string } -export interface CancelRequestBody { +export interface CancelRideBody { typeCode: CancelRequestType reason: string } @@ -49,43 +43,24 @@ export const rides = { assignDriver: (id: string, driverProfileId: string) => api.put(`/rides/${id}/driver`, { driverProfileId }).then(r => r.data), - activate: (id: string) => - api.patch(`/rides/${id}/activate`).then(r => r.data), - close: (id: string, meterend: number) => - api.patch(`/rides/${id}/close`, { meterend }).then(r => r.data), + api.post(`/rides/${id}/close`, { meterend }).then(r => r.data), - cancelRequests: { - getForRide: (rideId: string) => - api.get(`/rides/${rideId}/cancel-request`).then(r => r.data), - - raise: (rideId: string, body: CancelRequestBody) => - api.post(`/rides/${rideId}/cancel-request`, body).then(r => r.data), - - approve: (requestId: string) => - api.post(`/rides/cancel-requests/${requestId}/approve`).then(r => r.data), - - reject: (requestId: string) => - api.post(`/rides/cancel-requests/${requestId}/reject`).then(r => r.data), - }, + cancel: (id: string, body: CancelRideBody) => + api.post(`/rides/${id}/cancel`, body).then(r => r.data), } // ─── Loading Sheets ─────────────────────────────────────────────────────────── -export interface LoadingSheetItemBody { - itemId: string - quantityDispatched: number +export interface LoadingSheetCreateBody { + fK_RideId: string } -export interface LoadingSheetBody { - rideId: string - sourceWarehouseId: string - items: LoadingSheetItemBody[] -} - -export interface LoadingSheetReceiptItemBody { - itemId: string - quantityReceived: number +export interface LoadingSheetItemInput { + fK_ItemId: string + fK_WarehouseId: string + quantity: number + fK_ShopPOItemId?: string | null } export interface LoadingSheetListParams extends PageParams { @@ -100,17 +75,14 @@ export const loadingSheets = { get: (id: string) => api.get(`/loading-sheets/${id}`).then(r => r.data), - create: (body: LoadingSheetBody) => + create: (body: LoadingSheetCreateBody) => api.post('/loading-sheets', body).then(r => r.data), - confirmDispatch: (id: string) => - api.patch(`/loading-sheets/${id}/dispatch`).then(r => r.data), + updateItems: (id: string, items: LoadingSheetItemInput[]) => + api.put(`/loading-sheets/${id}/items`, { items }).then(r => r.data), - confirmReceipt: (id: string, items: LoadingSheetReceiptItemBody[]) => - api.patch(`/loading-sheets/${id}/receipt`, { items }).then(r => r.data), - - resolve: (id: string) => - api.patch(`/loading-sheets/${id}/resolve`).then(r => r.data), + confirm: (id: string) => + api.post(`/loading-sheets/${id}/confirm`).then(r => r.data), } // ─── Delivery Tasks ─────────────────────────────────────────────────────────── @@ -121,11 +93,8 @@ export interface DeliveryTaskItemQuantity { } export const deliveryTasks = { - generate: (rideId: string) => - api.post(`/rides/${rideId}/tasks/generate`).then(r => r.data), - listByRide: (rideId: string) => - api.get(`/rides/${rideId}/delivery-tasks`).then(r => r.data), + api.get(`/rides/${rideId}/tasks`).then(r => r.data), get: (id: string) => api.get(`/delivery-tasks/${id}`).then(r => r.data), diff --git a/distribution_fe/lib/api/returns-claims.ts b/distribution_fe/lib/api/returns-claims.ts index f7cea52..bd558af 100644 --- a/distribution_fe/lib/api/returns-claims.ts +++ b/distribution_fe/lib/api/returns-claims.ts @@ -35,11 +35,11 @@ export const saleReturns = { get: (id: string) => api.get(`/returns/${id}`).then(r => r.data), - listByOrder: (orderId: string) => - api.get(`/orders/${orderId}/returns`).then(r => r.data), + listByShopPO: (shopPOId: string) => + api.get(`/shop-pos/${shopPOId}/returns`).then(r => r.data), - create: (orderId: string, body: SaleReturnBody) => - api.post(`/orders/${orderId}/returns`, body).then(r => r.data), + create: (shopPOId: string, body: SaleReturnBody) => + api.post(`/shop-pos/${shopPOId}/returns`, body).then(r => r.data), updateReasons: (id: string, body: UpdateSaleReturnReasonsBody) => api.patch(`/returns/${id}/reasons`, body).then(r => r.data), diff --git a/distribution_fe/lib/api/sales.ts b/distribution_fe/lib/api/sales.ts index 026e920..ea1232d 100644 --- a/distribution_fe/lib/api/sales.ts +++ b/distribution_fe/lib/api/sales.ts @@ -1,101 +1,103 @@ import { api } from '@/lib/api' import type { PaginatedResponse, - SaleResponse, - OrderResponse, - OrderStatus, + ShopPOResponse, + InvoiceResponse, + InvoiceStatus, PaymentResponse, - SaleStatus, - PaymentStatus, PaymentMethod, + EntryMode, + ShopPOStatus, } from '@/types/api' import type { PageParams } from './master' -// ─── Sales ──────────────────────────────────────────────────────────────────── +// ─── Shop POs ───────────────────────────────────────────────────────────────── -export interface SaleItemBody { +export interface ShopPOItemBody { itemId: string quantity: number - unitPrice: number + unitPrice?: number | null } -export interface SaleBody { +export interface CreateShopPOBody { storeId: string - saleDate: string - rideId?: string | null - fulfillImmediately?: boolean - items: SaleItemBody[] - // TEMPORARY: required while auth doesn't resolve a logged-in user server-side — see testbug.md #28. - createdByUserId: string + items: ShopPOItemBody[] } -export interface SaleListParams extends PageParams { - storeId?: string - status?: SaleStatus - paymentStatus?: PaymentStatus - rideId?: string - from?: string - to?: string +export interface UpdateShopPOItemsBody { + items: ShopPOItemBody[] } -export const sales = { - list: (params?: SaleListParams) => - api.get>('/sales', { params }).then(r => r.data), +export interface ShopPOListParams extends PageParams { + agentId?: string + routeId?: string + shopId?: string + confirmed?: boolean + status?: ShopPOStatus +} + +export const shopPos = { + list: (params?: ShopPOListParams) => + api.get>('/shop-pos', { params }).then(r => r.data), get: (id: string) => - api.get(`/sales/${id}`).then(r => r.data), + api.get(`/shop-pos/${id}`).then(r => r.data), - create: (body: SaleBody) => - api.post('/sales', body).then(r => r.data), + create: (body: CreateShopPOBody) => + api.post('/shop-pos', body).then(r => r.data), + + updateItems: (id: string, body: UpdateShopPOItemsBody) => + api.put(`/shop-pos/${id}/items`, body).then(r => r.data), + + confirm: (id: string) => + api.post(`/shop-pos/${id}/confirm`).then(r => r.data), + + confirmAndCreateInvoice: (id: string) => + api.post(`/shop-pos/${id}/confirm-and-create-invoice`).then(r => r.data), cancel: (id: string) => - api.patch(`/sales/${id}/cancel`).then(r => r.data), + api.post(`/shop-pos/${id}/cancel`).then(r => r.data), } -// ─── Orders ─────────────────────────────────────────────────────────────────── -// GET /orders takes no query params and returns a plain array — no server-side -// filtering/pagination exists on the backend, unlike Sales/Payments. +// ─── Invoices ───────────────────────────────────────────────────────────────── -export const orders = { - list: () => - api.get('/orders').then(r => r.data), +export interface InvoiceListParams extends PageParams { + agentId?: string + routeId?: string + shopId?: string + status?: InvoiceStatus +} + +export const invoices = { + list: (params?: InvoiceListParams) => + api.get>('/invoices', { params }).then(r => r.data), get: (id: string) => - api.get(`/orders/${id}`).then(r => r.data), + api.get(`/invoices/${id}`).then(r => r.data), - update: (id: string, status: OrderStatus) => - api.put(`/orders/${id}`, { status }).then(r => r.data), + print: (id: string) => + api.post(`/invoices/${id}/print`).then(r => r.data), - delete: (id: string) => - api.delete(`/orders/${id}`), + finalize: (id: string) => + api.post(`/invoices/${id}/finalize`).then(r => r.data), } // ─── Payments ───────────────────────────────────────────────────────────────── export interface PaymentBody { - saleId: string amount: number method: PaymentMethod - // TEMPORARY: required while auth doesn't resolve a logged-in user server-side — see testbug.md #28. - collectedByUserId: string -} - -export interface PaymentListParams extends PageParams { - storeId?: string - saleId?: string - method?: PaymentMethod - from?: string - to?: string + entryMode?: EntryMode + chequeNumber?: string | null + chequeDate?: string | null + collectedByUserId?: string | null } export const payments = { - list: (params?: PaymentListParams) => - api.get>('/payments', { params }).then(r => r.data), + listByInvoice: (invoiceId: string) => + api.get(`/invoices/${invoiceId}/payments`).then(r => r.data), - get: (id: string) => - api.get(`/payments/${id}`).then(r => r.data), - - create: (body: PaymentBody) => - api.post('/payments', body).then(r => r.data), + create: (invoiceId: string, body: PaymentBody) => + api.post(`/invoices/${invoiceId}/payments`, body).then(r => r.data), } diff --git a/distribution_fe/package-lock.json b/distribution_fe/package-lock.json index 98302ae..806da56 100644 --- a/distribution_fe/package-lock.json +++ b/distribution_fe/package-lock.json @@ -16,6 +16,7 @@ "axios": "^1.19.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cn": "^0.3.0", "leaflet": "^1.9.4", "next": "16.2.6", "next-themes": "^0.4.6", @@ -3749,6 +3750,18 @@ "node": ">=6" } }, + "node_modules/cn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/cn/-/cn-0.3.0.tgz", + "integrity": "sha512-qRoU0ARrZD3Bbj1wKFftEKxPjSnzTEdFkf22NVhW+zU9D/wajhoP+qUZ5DChhhSOBCH1onV12hrmGqfu1+5Z2Q==", + "license": "MIT", + "bin": { + "cn": "bin/cn.mjs" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/code-block-writer": { "version": "13.0.3", "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", diff --git a/distribution_fe/package.json b/distribution_fe/package.json index ea376ad..d23cc1d 100644 --- a/distribution_fe/package.json +++ b/distribution_fe/package.json @@ -20,6 +20,7 @@ "axios": "^1.19.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cn": "^0.3.0", "leaflet": "^1.9.4", "next": "16.2.6", "next-themes": "^0.4.6", diff --git a/distribution_fe/types/api.ts b/distribution_fe/types/api.ts index 5f00b9e..0fb545b 100644 --- a/distribution_fe/types/api.ts +++ b/distribution_fe/types/api.ts @@ -5,21 +5,18 @@ export type LocationType = 'Warehouse' | 'Vehicle' | 'External' export type MovementType = | 'Sale' | 'CustomerReturn' | 'Transfer' | 'Damage' | 'Adjustment' | 'Load' | 'PurchaseReceipt' | 'PurchaseReturn' -export type LoadingSheetStatus = - | 'Pending' | 'DispatchConfirmed' | 'ReceiptConfirmed' - | 'DiscrepancyFlagged' | 'Resolved' -export type RideType = 'Delivery' | 'Sale' -export type RideStatus = - | 'Draft' | 'Open' | 'Active' | 'CancelRequested' | 'Cancelled' | 'Closed' +export type LoadingSheetStatus = 'Planned' | 'Confirmed' +export type RideStatus = 'Open' | 'Cancelled' | 'Closed' export type CancelRequestType = | 'VehicleBreakdown' | 'DriverUnavailable' | 'RouteIssue' | 'Other' -export type CancelRequestStatus = 'Pending' | 'Approved' | 'Rejected' export type PurchaseOrderStatus = | 'Issued' | 'PartiallyReceived' | 'Received' | 'Closed' | 'Cancelled' -export type SaleStatus = 'Pending' | 'Completed' | 'Cancelled' -export type OrderStatus = 'Pending' | 'PartiallyFulfilled' | 'Fulfilled' | 'Cancelled' +export type ShopPOStatus = 'Pending' | 'PartiallyFulfilled' | 'Fulfilled' | 'Cancelled' +export type InvoiceStatus = 'Draft' | 'Printed' | 'Finalized' +export type InvoiceCreationMode = 'ModeA' | 'ModeB' export type PaymentStatus = 'Pending' | 'PartiallyPaid' | 'Paid' -export type PaymentMethod = 'Cash' | 'Credit' +export type PaymentMethod = 'Cash' | 'Cheque' | 'Credit' +export type EntryMode = 'RealTime' | 'DayEndManual' export type DeliveryTaskStatus = 'Pending' | 'Delivered' | 'PartiallyDelivered' | 'Failed' export type VehicleType = 'Car' | 'Truck' | 'Van' | 'Motorcycle' | 'Bicycle' export type WarehouseType = @@ -457,7 +454,7 @@ export interface SaleReturnItemResponse { export interface SaleReturnResponse { id: string - orderId: string + shopPOId: string mode: ReturnMode totalCreditAmount: number orderTotalAmountAfter: number @@ -555,59 +552,45 @@ export interface DriverComplianceConfigResponse { export interface RideResponse { id: string - rideType: RideType status: RideStatus vehicleId: string vehicleNumberPlate: string driverProfileId: string driverFullName: string - routeId: string - routeName: string - sourceWarehouseId: string - sourceWarehouseName: string meterstart: number meterend: number startedAt: string | null - activatedAt: string | null closedAt: string | null createdAt: string } -export interface CancelRequestResponse { - id: string - rideId: string - typeCode: CancelRequestType - reason: string - requestedBy: string - requestedAt: string - status: CancelRequestStatus - approvedBy: string | null - approvedAt: string | null -} - // ─── Loading Sheets ─────────────────────────────────────────────────────────── export interface LoadingSheetItemResponse { id: string fK_ItemId: string itemName: string + fK_WarehouseId: string + warehouseName: string quantityDispatched: number - quantityReceived: number - quantityResolved: number + fK_ShopPOItemId: string | null +} + +export interface LoadingSheetOrderRef { + shopPOId: string } export interface LoadingSheetResponse { id: string fK_RideId: string - fK_SourceWarehouseId: string - warehouseName: string status: LoadingSheetStatus - dispatchConfirmedAt: string | null - dispatchConfirmedBy: string | null - receiptConfirmedAt: string | null - receiptConfirmedBy: string | null + populatedBy: string + populatedAt: string + confirmedAt: string | null + confirmedBy: string | null createdAt: string items: LoadingSheetItemResponse[] + orders: LoadingSheetOrderRef[] } // ─── Delivery Tasks ─────────────────────────────────────────────────────────── @@ -623,7 +606,7 @@ export interface DeliveryTaskItemResponse { export interface DeliveryTaskResponse { id: string fK_RideId: string - fK_OrderId: string + fK_ShopPOId: string storeId: string storeName: string sequence: number @@ -635,65 +618,71 @@ export interface DeliveryTaskResponse { createdAt: string } -// ─── Sales / Orders / Payments ──────────────────────────────────────────────── +// ─── ShopPO / Invoice / Payment ─────────────────────────────────────────────── -export interface SaleItemResponse { +export interface ShopPOItemResponse { + id: string itemId: string + itemName: string quantity: number quantityFulfilled: number unitPrice: number + isActive: boolean } -export interface SaleResponse { +export interface ShopPOResponse { id: string - saleDate: string storeId: string - createdByUserId: string - rideId: string | null + storeName: string + raisedById: string + invoiceId: string | null totalAmount: number - status: SaleStatus - paymentStatus: PaymentStatus - fulfillImmediately: boolean - completedAt: string | null - orderId: string - orderStatus: OrderStatus - orderFulfilledAt: string | null - items: SaleItemResponse[] + status: ShopPOStatus + confirmedAt: string | null + confirmedBy: string | null + fulfilledAt: string | null + items: ShopPOItemResponse[] isActive: boolean createdAt: string } -export interface OrderItemResponse { - itemId: string - quantity: number - quantityFulfilled: number - unitPrice: number -} - -export interface OrderResponse { +export interface InvoiceResponse { id: string - saleId: string - orderDate: string - storeId: string + shopPOId: string + storeName: string + status: InvoiceStatus + paymentStatus: PaymentStatus + createdBy: string + printedAt: string | null + printedBy: string | null + finalizedAt: string | null + finalizedBy: string | null totalAmount: number - status: OrderStatus - fulfilledAt: string | null - items: OrderItemResponse[] isActive: boolean createdAt: string } export interface PaymentResponse { id: string - saleId: string - storeId: string + invoiceId: string amount: number method: PaymentMethod + entryMode: EntryMode + chequeNumber: string | null + chequeDate: string | null collectedAt: string collectedBy: string + recordedBy: string | null createdAt: string } +export interface SysConfigResponse { + key: string + value: string + updatedAt: string + updatedBy: string | null +} + // ─── API Error ──────────────────────────────────────────────────────────────── export interface ApiError {