Compare commits
111
Commits
Vinay
..
0bd70d3cf4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bd70d3cf4 | ||
|
|
a7538ebc6d | ||
|
|
7a1d2fcf91 | ||
|
|
0247d68b50 | ||
|
|
062365ed51 | ||
|
|
17d5422c43 | ||
|
|
0025d50677 | ||
|
|
954c9088e3 | ||
|
|
9aafe5a95c | ||
|
|
fc43e84302 | ||
|
|
1e7db629ae | ||
|
|
0d203a880f | ||
|
|
68107ca7f0 | ||
|
|
2ee82a2eed | ||
|
|
75495afd73 | ||
|
|
9528134eda | ||
|
|
a9961027d1 | ||
|
|
444648178a | ||
|
|
36bf1695ca | ||
|
|
916cd7b275 | ||
|
|
ae539ae285 | ||
|
|
36c11fabc1 | ||
|
|
915094e49f | ||
|
|
c8d8458f8c | ||
|
|
b27f2feadb | ||
|
|
7d3af46a22 | ||
|
|
f576d33ec9 | ||
|
|
4e80a3d9f2 | ||
|
|
06637c21ee | ||
|
|
0de3eb7142 | ||
|
|
470893165a | ||
|
|
8b3af1adc0 | ||
|
|
dad5844b27 | ||
|
|
d51c8c7547 | ||
|
|
0c9313b77c | ||
|
|
ce622a118f | ||
|
|
ed1e7546a7 | ||
|
|
cad5a647f1 | ||
|
|
e68b24b557 | ||
|
|
bcdf15a034 | ||
|
|
943f83a33f | ||
|
|
3d20b09464 | ||
|
|
fc402e0232 | ||
|
|
a889b48bd1 | ||
|
|
1e02deb1b1 | ||
|
|
7d99a11e14 | ||
|
|
711983f312 | ||
|
|
1c1a25ade9 | ||
|
|
ad7b3effcc | ||
|
|
d8d2caddfb | ||
|
|
75c79ba02b | ||
|
|
18afa76d56 | ||
|
|
c4985f9690 | ||
|
|
0a0e627b4a | ||
|
|
34a0c5f5bb | ||
|
|
ef181bce1a | ||
|
|
182ad004fb | ||
|
|
c80a347bef | ||
|
|
dac0fcb85b | ||
|
|
9fb657a0fb | ||
|
|
f2b05b229d | ||
|
|
fb4f1a0995 | ||
|
|
d17ea1da6a | ||
|
|
712543ec3c | ||
|
|
ecf31b1b74 | ||
|
|
ae11f05aba | ||
|
|
4d7f5ccdfb | ||
|
|
d28a3215d1 | ||
|
|
387e203bc8 | ||
|
|
82c66d4b3a | ||
|
|
c96656086e | ||
|
|
ade8901649 | ||
|
|
3f4c53c6cc | ||
|
|
bb51bb448f | ||
|
|
7ef110eaf7 | ||
|
|
a1751b8918 | ||
|
|
3b5a0379cb | ||
|
|
09bc25346d | ||
|
|
9aadfbbd24 | ||
|
|
38c6a32114 | ||
|
|
932657c2b2 | ||
|
|
ce1f5f9b04 | ||
|
|
fc361e3133 | ||
|
|
141d8961e4 | ||
|
|
32d4ea28f5 | ||
|
|
67b7c5aa9a | ||
|
|
be03724217 | ||
|
|
d9dcda0724 | ||
|
|
211e55a373 | ||
|
|
5144456721 | ||
|
|
d475d3828b | ||
|
|
f8263e8a35 | ||
|
|
bd46d5ae52 | ||
|
|
9633983dec | ||
|
|
9a60105ed3 | ||
|
|
338f86a5f5 | ||
|
|
fc94c7aacc | ||
|
|
6ca803d7f2 | ||
|
|
40933a2713 | ||
|
|
d8a4483c3c | ||
|
|
db7bdffe33 | ||
|
|
e94928ae7f | ||
|
|
4e069e0300 | ||
|
|
7e8f70a7c2 | ||
|
|
4688b92314 | ||
|
|
471c043218 | ||
|
|
d8ab337fde | ||
|
|
b5c28dd288 | ||
|
|
3cd5c4c471 | ||
|
|
2fecc4b3fd | ||
|
|
0b75681236 |
@@ -43,4 +43,13 @@ bin/
|
|||||||
application.yaml
|
application.yaml
|
||||||
initial-data.sql
|
initial-data.sql
|
||||||
app.yaml
|
app.yaml
|
||||||
|
app.properties
|
||||||
*.env.json
|
*.env.json
|
||||||
|
|
||||||
|
### API Logs ###
|
||||||
|
api.log
|
||||||
|
api.2024*
|
||||||
|
|
||||||
|
### Excel FIles ###
|
||||||
|
./excel
|
||||||
|
./.kotlin
|
||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="KotlinJpsPluginSettings">
|
<component name="KotlinJpsPluginSettings">
|
||||||
<option name="version" value="1.9.22" />
|
<option name="version" value="1.7.10" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+1
-2
@@ -10,9 +10,8 @@
|
|||||||
<option value="$PROJECT_DIR$/../txn_workflow/pom.xml" />
|
<option value="$PROJECT_DIR$/../txn_workflow/pom.xml" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
<option name="workspaceImportForciblyTurnedOn" value="true" />
|
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="zulu-17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+1
@@ -2,5 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/../txn_workflow" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Binary file not shown.
@@ -7,8 +7,7 @@ Authorization: {{auth-token}}
|
|||||||
"data": {
|
"data": {
|
||||||
"number": "KA01HD6677",
|
"number": "KA01HD6677",
|
||||||
"owner": "gowthaman"
|
"owner": "gowthaman"
|
||||||
},
|
}
|
||||||
"uniqueIdentifier": ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
### create row
|
### create row
|
||||||
@@ -52,18 +51,20 @@ GET http://localhost:9001/api/log/log-0000000001
|
|||||||
Authorization: Bearer {{auth-token}}
|
Authorization: Bearer {{auth-token}}
|
||||||
|
|
||||||
### get row
|
### get row
|
||||||
GET http://localhost:9001/api/vehicle/KA01HD6667
|
GET http://localhost:9001/api/vehicle/KA01HD6677
|
||||||
Authorization: Bearer {{auth-token}}
|
Authorization: Bearer {{auth-token}}
|
||||||
|
|
||||||
### query row
|
|
||||||
POST http://localhost:9001/api/vehicle/query
|
### search row
|
||||||
|
POST http://localhost:9001/api/vehicle/search
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: {{set-auth-token}}
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
{
|
{
|
||||||
"sql": "select sys_pk, tenant_id, deleted_on, deleted_by, deleted, version, created_at, modified_at, created_by, modified_by, data, tags, comments, unique_identifier, entity_name from data_model where data ->> 'number' = :number",
|
"dateRange": ["2024-05-01", "2024-05-24"],
|
||||||
"params": {
|
"params": {
|
||||||
"number": "KA03HD6064"
|
"number": "KA01HD6677",
|
||||||
|
"owner": "gowthaman"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,20 +94,16 @@ Authorization: {{auth-token}}
|
|||||||
DELETE http://localhost:9001/api/vehicle/KA01HD6667
|
DELETE http://localhost:9001/api/vehicle/KA01HD6667
|
||||||
Authorization: {{auth-token}}
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
### get products
|
### get po for id
|
||||||
GET http://localhost:9001/api/vendor/product
|
GET http://localhost:9001/api/vendor/product
|
||||||
Authorization: {{auth-token}}
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
### get products by hsn code
|
### get product for id
|
||||||
GET http://localhost:9001/api/vendor/product/#123
|
GET http://localhost:9001/api/vendor/product/7
|
||||||
Authorization: {{auth-token}}
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
### create excel for products
|
### get row
|
||||||
POST http://localhost:9001/api/vendor/product/product-excel
|
GET http://localhost:9001/api/vendor/product/7
|
||||||
Authorization: {{auth-token}}
|
|
||||||
|
|
||||||
### excel read
|
|
||||||
GET http://localhost:9001/api/vendor/product/validation
|
|
||||||
Authorization: Bearer {{auth-token}}
|
Authorization: Bearer {{auth-token}}
|
||||||
|
|
||||||
### create product
|
### create product
|
||||||
@@ -134,9 +131,258 @@ Authorization: {{auth-token}}
|
|||||||
|
|
||||||
|
|
||||||
### delete a row
|
### delete a row
|
||||||
DELETE http://localhost:9001/api/vendor/product/#1
|
DELETE http://localhost:9001/api/vendor/product/2
|
||||||
Authorization: {{auth-token}}
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
###
|
### create vendor
|
||||||
POST http://localhost:9001/api/vendor/product/import
|
POST http://localhost:9001/api/vendor/
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "arsalan",
|
||||||
|
"msme": "1234",
|
||||||
|
"gstNumber": "GST123",
|
||||||
|
"address": "Bangalore",
|
||||||
|
"rating": 2,
|
||||||
|
"contacts": [
|
||||||
|
{
|
||||||
|
"name": "contact1",
|
||||||
|
"email": "abc@cyz.com",
|
||||||
|
"mobile": "01234567890"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
### create batch vendor
|
||||||
|
POST http://localhost:9001/api/vendor/batch
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "john",
|
||||||
|
"description": "5678",
|
||||||
|
"hsnCode": "5678",
|
||||||
|
"gstNumber": "GST567",
|
||||||
|
"address": "Mumbai",
|
||||||
|
"rating": 4,
|
||||||
|
"contacts": [
|
||||||
|
{
|
||||||
|
"name": "contact1",
|
||||||
|
"email": "xyz@abc.com",
|
||||||
|
"phone": "9876543210"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "emma",
|
||||||
|
"description": "7890",
|
||||||
|
"hsnCode": "7890",
|
||||||
|
"gstNumber": "GST789",
|
||||||
|
"address": "Delhi",
|
||||||
|
"rating": 3,
|
||||||
|
"contacts": [
|
||||||
|
{
|
||||||
|
"name": "contact2",
|
||||||
|
"email": "def@uvw.com",
|
||||||
|
"phone": "8765432109"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "alex",
|
||||||
|
"description": "2345",
|
||||||
|
"hsnCode": "2345",
|
||||||
|
"gstNumber": "GST234",
|
||||||
|
"address": "Chennai",
|
||||||
|
"rating": 5,
|
||||||
|
"contacts": [
|
||||||
|
{
|
||||||
|
"name": "contact3",
|
||||||
|
"email": "ghi@rst.com",
|
||||||
|
"phone": "7654321098"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
### GET ALL VENDORS
|
||||||
|
POST http://localhost:9001/api/vendor/getAll
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"common": {
|
||||||
|
"sortAsc": true
|
||||||
|
},
|
||||||
|
"vendorFilters": {
|
||||||
|
"nameLike": "a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
### create batch pos
|
||||||
|
POST http://localhost:9001/api/vendor/po/batch
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"productId": "1232",
|
||||||
|
"productName": "chair",
|
||||||
|
"unitPrice": 34.2,
|
||||||
|
"quantity": 10,
|
||||||
|
"description": "wooden chair"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"referenceQuotation": "12323",
|
||||||
|
"totalAmount": 342,
|
||||||
|
"poNum": "1",
|
||||||
|
"poDate": "2024-01-10",
|
||||||
|
"validTill": "2024-02-10",
|
||||||
|
"tnc": ["tnc1", "tnc2"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"productId": "5678",
|
||||||
|
"productName": "table",
|
||||||
|
"unitPrice": 45.5,
|
||||||
|
"quantity": 5,
|
||||||
|
"description": "glass table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"referenceQuotation": "56789",
|
||||||
|
"totalAmount": 227.5,
|
||||||
|
"poNum": "2",
|
||||||
|
"poDate": "2024-10-25",
|
||||||
|
"validTill": "2024-10-25",
|
||||||
|
"tnc": ["tnc3", "tnc4"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"productId": "91011",
|
||||||
|
"productName": "lamp",
|
||||||
|
"unitPrice": 15.75,
|
||||||
|
"quantity": 20,
|
||||||
|
"description": "floor lamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"referenceQuotation": "9101112",
|
||||||
|
"totalAmount": 315,
|
||||||
|
"poNum": "3",
|
||||||
|
"poDate": "2024-10-25",
|
||||||
|
"validTill": "2024-12-25",
|
||||||
|
"tnc": ["tnc5", "tnc6"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
### GET ALL POS
|
||||||
|
POST http://localhost:9001/api/vendor/po/getAll
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"common" : {},
|
||||||
|
"poFilters": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
### CREATE QUOTES
|
||||||
|
POST http://localhost:9001/api/vendor/quote/batch
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"productId": "1232",
|
||||||
|
"productName": "chair",
|
||||||
|
"unitPrice": 34.2,
|
||||||
|
"quantity": 10,
|
||||||
|
"description": "wooden chair"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reqForQuoteNum": "12323",
|
||||||
|
"totalAmount": 342,
|
||||||
|
"quoteNum": "1",
|
||||||
|
"quoteDate": "2024-10-24",
|
||||||
|
"validTill": "2024-11-24",
|
||||||
|
"tnc": ["tnc1", "tnc2"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"productId": "5678",
|
||||||
|
"productName": "table",
|
||||||
|
"unitPrice": 45.5,
|
||||||
|
"quantity": 5,
|
||||||
|
"description": "glass table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reqForQuoteNum": "56789",
|
||||||
|
"totalAmount": 227.5,
|
||||||
|
"quoteNum": "2",
|
||||||
|
"quoteDate": "2024-10-25",
|
||||||
|
"validTill": "2024-11-25",
|
||||||
|
"tnc": ["tnc3", "tnc4"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"productId": "91011",
|
||||||
|
"productName": "lamp",
|
||||||
|
"unitPrice": 15.75,
|
||||||
|
"quantity": 20,
|
||||||
|
"description": "floor lamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reqForQuoteNum": "9101112",
|
||||||
|
"totalAmount": 315,
|
||||||
|
"quoteNum": "3",
|
||||||
|
"quoteDate": "2024-10-25",
|
||||||
|
"validTill": "2024-12-25",
|
||||||
|
"tnc": ["tnc5", "tnc6"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
### GET ALL QUOTES
|
||||||
|
POST http://localhost:9001/api/vendor/quote/getAll
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"common" : {},
|
||||||
|
"quoteFilters": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### GET ALL PRODUCTS
|
||||||
|
POST http://localhost:9001/api/vendor/product/getAll
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"common" : {},
|
||||||
|
"quoteFilters": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
### GET NEXT PO SEQ NUMBER
|
||||||
|
GET http://localhost:9001/api/vendor/po/next
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
|
||||||
|
### GET NEXT QUOTE SEW NUMBER
|
||||||
|
GET http://localhost:9001/api/vendor/quote/next
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: {{auth-token}}
|
||||||
|
|
||||||
|
### GET NEXT INCOMING SEW NUMBER
|
||||||
|
GET http://localhost:9001/api/vendor/incoming/next
|
||||||
|
Content-Type: application/json
|
||||||
Authorization: {{auth-token}}
|
Authorization: {{auth-token}}
|
||||||
@@ -18,6 +18,8 @@ app:
|
|||||||
client: rmc
|
client: rmc
|
||||||
scripts:
|
scripts:
|
||||||
path: /Users/gowthaman.b/IdeaProjects/rmc_modules_api/src/main/resources/scripts
|
path: /Users/gowthaman.b/IdeaProjects/rmc_modules_api/src/main/resources/scripts
|
||||||
|
integration:
|
||||||
|
rmc: https://www.readymixerp.com
|
||||||
security:
|
security:
|
||||||
enforce_role_restriction: 'true'
|
enforce_role_restriction: 'true'
|
||||||
private_key: |-
|
private_key: |-
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#DO Not edit this file, copy to your HOME Directory and then rename it to app.yaml and then edit it
|
||||||
|
app:
|
||||||
|
db:
|
||||||
|
pass: password
|
||||||
|
url: jdbc:postgresql://10.10.10.211/arsalan_rmc_module_app
|
||||||
|
user: arsalan
|
||||||
|
name: arsalan_rmc_module_app
|
||||||
|
run_migration: 'true'
|
||||||
|
cors:
|
||||||
|
enabled: 'true'
|
||||||
|
hosts: www.readymixerp.com,app.readymixerp.com
|
||||||
|
port: '9001'
|
||||||
|
cache:
|
||||||
|
redis_uri: redis://10.10.10.112:6379/
|
||||||
|
iam:
|
||||||
|
url: https://auth.readymixerp.com
|
||||||
|
realm: rmc-dev
|
||||||
|
client_redirect_uri: http://localhost:9001/auth/code
|
||||||
|
client: rmc
|
||||||
|
scripts:
|
||||||
|
path: /Users/gowthaman.b/IdeaProjects/rmc_modules_api/src/main/resources/scripts
|
||||||
|
security:
|
||||||
|
private_key: |-
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD4ba8OhlyB9MUx
|
||||||
|
MFmT8c9sOKqXOG6ZM6qLxr5SnY1au47rYsHXt8Hb+tTUxpkf+5bndaZYGVgQ1mtw
|
||||||
|
eEVj3qZq9A+FnxxwZ9uIIdbOUPvsZLzNYnK3bFFRsmWMf30gDs6ZdS63b2tnXXE0
|
||||||
|
aoItwVguElUKVXKUymS0VlBB0ZLCYTlD6Q4sDm7HGXJZj5kVNVbBCBe42yLx8Y1F
|
||||||
|
TyNL8nPSS+SAdLUaPJ/6j+741+exAIOc0rSBJOMF0XNOwBZ85EuOiPa0e1sUz0qj
|
||||||
|
VfmZyeRFxkSWJBnqum1jrVFp55bMb37DYtZa0aFIcPdDfY42frDlPLcI4zzRwCn3
|
||||||
|
ggHL/nL9AgMBAAECggEAJ85sxu8zl8/l4EsG3M8EdVWidrGgUyRgDElFCiLcWVta
|
||||||
|
prqVJIt5YNYRJU5J5Jc2fRGxHPEOrJVW84IUsvskVQM/ZiHyd3ZvdaGKdFZYpO5t
|
||||||
|
VvGSlR53l0IhGxal24L+isCn7X+ec5pu6b8JQJX4RbBConHCTDdz/yDMzQcXiiqj
|
||||||
|
ezzSovZ1Xy/2dn7sOTFtEZi47d3AhBnjh8Xqk3Dc9UChooxuIU6WEbqWFxEkbzJS
|
||||||
|
sXIv9xADVDqFqjHGv6Tk1W+y7y8M2EHosJfhO0LmWFL7nUdw0WSJV+UqQxHrUSJs
|
||||||
|
SnYHkKRTYl2ljpjkuECp/YqUqdlNq/5T5jBE6cyopwKBgQD6+XGZfssdAqfnaEK2
|
||||||
|
nHdUAdklUFAFQpSmwIUwTZEHDC/CD+ErVjfbEfZ2mFOvWAIMwLmiLFuDT7E5sHaT
|
||||||
|
K4A2DQ8KyU3iJkH4nhxdYepLc7MSYElkn6fHNrXcJ9vPACmrtoa9rVW/LpAjsRq6
|
||||||
|
fDxLo12/+EmFvpZ0oEAIQXk6ZwKBgQD9ZzBgPapI8m7cjcdojqq0dJ2M5Sw7Bx5n
|
||||||
|
VFOC3H4Cx0xWTdwwZ9CZQ4v/XiiHiUGzwhfkNJ2x3DdpUCkPDD8o3cFXPRW4GsjD
|
||||||
|
kv/D0kL/JJAesG9XB9yMTMBoe2yGMudDVc7SYgUI2YXhmHYkpcjSzM0DftLL2Z47
|
||||||
|
GY1h385Q+wKBgGTRxe/Kfp+lzHtqZ7ph+pG1uFyD+dFTINIn7pkr38G8BIdpx6OY
|
||||||
|
HBIWEjMsGBoNOa2T0j6yoQSMA/7Pw6J1TCjqcAt+OJpLkh7krTJaPjuXO+163qDc
|
||||||
|
fhLKCJ5rKKLsRtEjHtedhR+q/d5IrBsUA0jDVMrkW+ytVlV9dpuaaa+rAoGASON8
|
||||||
|
m8JBD/iEAPbbK+0VlxCQHO3ymgwDJ8+usc6AhIYVJCIDOv0xmFRAmbTYzZuihXVH
|
||||||
|
8AFedsGUQrunA8gPBs86hMByVeGGbBMFdKsvUDqRJfK0JAGD4+tT0PnnjnZn5Qty
|
||||||
|
kTtWnWQMSYbUPNhe+pukQOQi+DXheLhx3XxF2S8CgYEAopLjGIR/xeuV7QkGJfCO
|
||||||
|
d2wEJROBPd3pbDlR4fLDO8RCw3irFYQgQd9WgGJY5KgyfjKLHkK7DMQKn+/yfUp5
|
||||||
|
UKeesBDXATpyQQrpfoKIhhZKtYphOwvIzugtLsd5sza++sjC9RwkRmYr0rzlHdUl
|
||||||
|
vtr3fru0Bzven2MeiQnqmCM=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
public_key: |-
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+G2vDoZcgfTFMTBZk/HP
|
||||||
|
bDiqlzhumTOqi8a+Up2NWruO62LB17fB2/rU1MaZH/uW53WmWBlYENZrcHhFY96m
|
||||||
|
avQPhZ8ccGfbiCHWzlD77GS8zWJyt2xRUbJljH99IA7OmXUut29rZ11xNGqCLcFY
|
||||||
|
LhJVClVylMpktFZQQdGSwmE5Q+kOLA5uxxlyWY+ZFTVWwQgXuNsi8fGNRU8jS/Jz
|
||||||
|
0kvkgHS1Gjyf+o/u+NfnsQCDnNK0gSTjBdFzTsAWfORLjoj2tHtbFM9Ko1X5mcnk
|
||||||
|
RcZEliQZ6rptY61RaeeWzG9+w2LWWtGhSHD3Q32ONn6w5Ty3COM80cAp94IBy/5y
|
||||||
|
/QIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
+34
-7
@@ -1,8 +1,11 @@
|
|||||||
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.9.22"
|
kotlin("jvm") version "2.0.0"
|
||||||
kotlin("kapt") version "1.9.22"
|
kotlin("kapt") version "2.0.0"
|
||||||
id("idea")
|
id("idea")
|
||||||
id("io.ebean") version "13.23.2"
|
id("io.ebean") version "13.23.2"
|
||||||
|
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,6 +18,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation(kotlin("test"))
|
testImplementation(kotlin("test"))
|
||||||
|
implementation("net.jodah:expiringmap:0.5.11")
|
||||||
implementation("javax.xml.bind:jaxb-api:2.3.1")
|
implementation("javax.xml.bind:jaxb-api:2.3.1")
|
||||||
implementation("com.sun.xml.bind:jaxb-impl:2.3.9")
|
implementation("com.sun.xml.bind:jaxb-impl:2.3.9")
|
||||||
implementation("io.javalin:javalin:5.6.3")
|
implementation("io.javalin:javalin:5.6.3")
|
||||||
@@ -27,10 +31,8 @@ dependencies {
|
|||||||
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.+")
|
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.+")
|
||||||
implementation("ch.qos.logback:logback-core:1.4.12")
|
implementation("ch.qos.logback:logback-core:1.4.12")
|
||||||
implementation("ch.qos.logback:logback-classic:1.4.12")
|
implementation("ch.qos.logback:logback-classic:1.4.12")
|
||||||
implementation("org.bitbucket.b_c:jose4j:0.9.3")
|
implementation("org.bitbucket.b_c:jose4j:0.9.4")
|
||||||
implementation("redis.clients:jedis:5.0.2")
|
implementation("redis.clients:jedis:5.0.2")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-scripting-jsr223:1.9.22")
|
|
||||||
implementation("org.jetbrains.kotlin:kotlin-script-runtime:1.9.22")
|
|
||||||
implementation("org.bouncycastle:bcprov-jdk18on:1.76")
|
implementation("org.bouncycastle:bcprov-jdk18on:1.76")
|
||||||
implementation("org.bouncycastle:bcpkix-jdk18on:1.76")
|
implementation("org.bouncycastle:bcpkix-jdk18on:1.76")
|
||||||
implementation("org.yaml:snakeyaml:2.2")
|
implementation("org.yaml:snakeyaml:2.2")
|
||||||
@@ -38,8 +40,9 @@ dependencies {
|
|||||||
implementation("org.apache.httpcomponents:httpclient:4.5.14")
|
implementation("org.apache.httpcomponents:httpclient:4.5.14")
|
||||||
implementation("org.apache.poi:poi:5.2.3")
|
implementation("org.apache.poi:poi:5.2.3")
|
||||||
implementation("org.apache.poi:poi-ooxml:5.2.3")
|
implementation("org.apache.poi:poi-ooxml:5.2.3")
|
||||||
api ("net.cactusthorn.config:config-core:0.81")
|
implementation("com.google.code.gson:gson:2.8.9")
|
||||||
api ("net.cactusthorn.config:config-yaml:0.81")
|
api("net.cactusthorn.config:config-core:0.81")
|
||||||
|
api("net.cactusthorn.config:config-yaml:0.81")
|
||||||
kapt("net.cactusthorn.config:config-compiler:0.81")
|
kapt("net.cactusthorn.config:config-compiler:0.81")
|
||||||
kapt("io.ebean:kotlin-querybean-generator:13.23.2")
|
kapt("io.ebean:kotlin-querybean-generator:13.23.2")
|
||||||
}
|
}
|
||||||
@@ -52,6 +55,30 @@ kotlin {
|
|||||||
jvmToolchain(17)
|
jvmToolchain(17)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
named<ShadowJar>("shadowJar") {
|
||||||
|
archiveBaseName.set("rest-api")
|
||||||
|
mergeServiceFiles()
|
||||||
|
manifest {
|
||||||
|
attributes(mapOf("Main-Class" to "com.restapi.MainKt"))
|
||||||
|
}
|
||||||
|
isZip64 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.distTar {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
tasks.distZip {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
tasks.shadowDistTar {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
tasks.shadowDistZip {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass.set("com.restapi.MainKt")
|
mainClass.set("com.restapi.MainKt")
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -42,7 +42,7 @@ class AppAccessManager : AccessManager {
|
|||||||
Role.DbOps -> listOf("ROLE_DB_OPS")
|
Role.DbOps -> listOf("ROLE_DB_OPS")
|
||||||
Role.Entity -> loadEntityActionRole(entity, action)
|
Role.Entity -> loadEntityActionRole(entity, action)
|
||||||
is Role.Standard -> role.action.toList().map { "ROLE_${entity}_${it}" }
|
is Role.Standard -> role.action.toList().map { "ROLE_${entity}_${it}" }
|
||||||
is Role.Explicit -> role.roles
|
is Role.Explicit -> role.roles.toList() + listOf("ROLE_ADMIN")
|
||||||
}.map(String::uppercase)
|
}.map(String::uppercase)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +60,15 @@ class AppAccessManager : AccessManager {
|
|||||||
//if role is allowed, or enforcement is turned off or no roles are explicitly allowed
|
//if role is allowed, or enforcement is turned off or no roles are explicitly allowed
|
||||||
handler.handle(ctx)
|
handler.handle(ctx)
|
||||||
} else {
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
"entity - {}, action {}, user roles = {}, allowed = {}, isAllowed? {}, enforce? {}",
|
||||||
|
entity,
|
||||||
|
action,
|
||||||
|
currentRoles(),
|
||||||
|
allowedRoles,
|
||||||
|
isAllowed,
|
||||||
|
appConfig.enforceRoleRestriction()
|
||||||
|
)
|
||||||
ctx.status(HttpStatus.FORBIDDEN).result("user not allowed to do this")
|
ctx.status(HttpStatus.FORBIDDEN).result("user not allowed to do this")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+171
-126
@@ -6,10 +6,9 @@ import com.restapi.config.AppConfig.Companion.appConfig
|
|||||||
import com.restapi.config.Auth.validateAuthToken
|
import com.restapi.config.Auth.validateAuthToken
|
||||||
import com.restapi.controllers.*
|
import com.restapi.controllers.*
|
||||||
import com.restapi.domain.DataNotFoundException
|
import com.restapi.domain.DataNotFoundException
|
||||||
import com.restapi.domain.Product
|
|
||||||
import com.restapi.domain.Session.a
|
|
||||||
import com.restapi.domain.Session.currentTenant
|
import com.restapi.domain.Session.currentTenant
|
||||||
import com.restapi.domain.Session.currentUser
|
import com.restapi.domain.Session.currentUser
|
||||||
|
import com.restapi.domain.Session.currentUserPlants
|
||||||
import com.restapi.domain.Session.objectMapper
|
import com.restapi.domain.Session.objectMapper
|
||||||
import com.restapi.domain.Session.setAuthorizedUser
|
import com.restapi.domain.Session.setAuthorizedUser
|
||||||
import com.restapi.domain.Session.signPayload
|
import com.restapi.domain.Session.signPayload
|
||||||
@@ -25,7 +24,6 @@ import io.javalin.http.util.RateLimitUtil
|
|||||||
import io.javalin.json.JavalinJackson
|
import io.javalin.json.JavalinJackson
|
||||||
import org.jose4j.jwt.consumer.InvalidJwtException
|
import org.jose4j.jwt.consumer.InvalidJwtException
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.InputStream
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -39,21 +37,19 @@ fun main(args: Array<String>) {
|
|||||||
val viewRole = Role.Standard(Action.VIEW)
|
val viewRole = Role.Standard(Action.VIEW)
|
||||||
val createRole = Role.Standard(Action.CREATE)
|
val createRole = Role.Standard(Action.CREATE)
|
||||||
val updateRole = Role.Standard(Action.UPDATE)
|
val updateRole = Role.Standard(Action.UPDATE)
|
||||||
val approveOrRejectRole = Role.Standard(Action.APPROVE)
|
val appAdmin = Role.Explicit("ROLE_ADMIN")
|
||||||
|
|
||||||
//todo, create roles in keycloak based on entity and actions
|
//todo, create roles in keycloak based on entity and actions
|
||||||
|
|
||||||
//ratelimit based on IP Only
|
//ratelimit based on IP Only
|
||||||
RateLimitUtil.keyFunction = { ctx -> ctx.header("X-Forwarded-For")?.split(",")?.get(0) ?: ctx.ip() }
|
RateLimitUtil.keyFunction = { ctx -> ctx.header("X-Forwarded-For")?.split(",")?.get(0) ?: ctx.ip() }
|
||||||
Javalin
|
Javalin.create { cfg ->
|
||||||
.create { cfg ->
|
|
||||||
cfg.http.generateEtags = true
|
cfg.http.generateEtags = true
|
||||||
if (appConfig.corsEnabled()) {
|
if (appConfig.corsEnabled()) {
|
||||||
cfg.plugins.enableCors { container ->
|
cfg.plugins.enableCors { container ->
|
||||||
container.add {
|
container.add {
|
||||||
it.allowHost(
|
it.allowHost(
|
||||||
"http://localhost:5173",
|
"http://localhost:5173", *appConfig.corsHosts().toTypedArray()
|
||||||
*appConfig.corsHosts().toTypedArray()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,22 +58,20 @@ fun main(args: Array<String>) {
|
|||||||
cfg.compression.gzipOnly()
|
cfg.compression.gzipOnly()
|
||||||
cfg.jsonMapper(JavalinJackson(objectMapper))
|
cfg.jsonMapper(JavalinJackson(objectMapper))
|
||||||
cfg.accessManager(AppAccessManager())
|
cfg.accessManager(AppAccessManager())
|
||||||
}
|
}.routes {
|
||||||
.routes {
|
|
||||||
path("/auth") {
|
path("/auth") {
|
||||||
|
|
||||||
get("/endpoint", Auth::endPoint)
|
get("/endpoint", Auth::endPoint)
|
||||||
get("/init", Auth::init)
|
get("/init", Auth::init)
|
||||||
get("/code", Auth::code)
|
get("/code", Auth::code)
|
||||||
get("/keys", Auth::keys)
|
get("/keys", Auth::keys)
|
||||||
|
post("/logout", Auth::logout)
|
||||||
post("/refresh", Auth::refreshToken)
|
post("/refresh", Auth::refreshToken)
|
||||||
}
|
}
|
||||||
before("/api/*") { ctx ->
|
before("/api/*") { ctx ->
|
||||||
|
|
||||||
NaiveRateLimit.requestPerTimeUnit(
|
NaiveRateLimit.requestPerTimeUnit(
|
||||||
ctx,
|
ctx, appConfig.rateLimit().getOrDefault(10000), TimeUnit.MINUTES
|
||||||
appConfig.rateLimit().getOrDefault(30),
|
|
||||||
TimeUnit.MINUTES
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val authToken = ctx.getAuthHeader() ?: throw UnauthorizedResponse()
|
val authToken = ctx.getAuthHeader() ?: throw UnauthorizedResponse()
|
||||||
@@ -87,9 +81,6 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
setAuthorizedUser(validateAuthToken(authToken = authToken))
|
setAuthorizedUser(validateAuthToken(authToken = authToken))
|
||||||
|
|
||||||
if (appConfig.enforcePayloadEncryption()) {
|
|
||||||
//todo: decrypt the request from user
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
after("/api/*") {
|
after("/api/*") {
|
||||||
|
|
||||||
@@ -101,13 +92,13 @@ fun main(args: Array<String>) {
|
|||||||
it.header("X-Checksum", outEncoded)
|
it.header("X-Checksum", outEncoded)
|
||||||
it.header("X-Signature", signPayload(outEncoded))
|
it.header("X-Signature", signPayload(outEncoded))
|
||||||
|
|
||||||
if (appConfig.enforcePayloadEncryption()) {
|
|
||||||
//todo: encrypt and send the response back to user
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
path("/api") {
|
path("/api") {
|
||||||
|
|
||||||
|
get("/plants") {
|
||||||
|
it.json(currentUserPlants())
|
||||||
|
}
|
||||||
post("/audit/{action}") {
|
post("/audit/{action}") {
|
||||||
logger.warn("User ${currentUser()} of tenant ${currentTenant()} has performed ${it.pathParam("action")} @ ${LocalDateTime.now()}")
|
logger.warn("User ${currentUser()} of tenant ${currentTenant()} has performed ${it.pathParam("action")} @ ${LocalDateTime.now()}")
|
||||||
it.json(mapOf("status" to true))
|
it.json(mapOf("status" to true))
|
||||||
@@ -115,156 +106,210 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
path("/vendor") {
|
path("/vendor") {
|
||||||
path("/") {
|
path("/") {
|
||||||
post("", Vendor::create, Roles(Role.Explicit(listOf("ROLE_VENDOR_CREATE", "ROLE_ADMIN"))))
|
post("", VendorCtrl::create, Roles(Role.Explicit("ROLE_VENDOR_CREATE")))
|
||||||
get(
|
post("/batch", VendorCtrl::createBatch, Roles(Role.Explicit("ROLE_VENDOR_CREATE")))
|
||||||
"",
|
get("/{id}", VendorCtrl::get, Roles(Role.Explicit("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE")))
|
||||||
Vendor::get,
|
post(
|
||||||
Roles(Role.Explicit(listOf("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE", "ROLE_ADMIN")))
|
"/getAll", VendorCtrl::getAll
|
||||||
)
|
)
|
||||||
get(
|
get(
|
||||||
"quotes/{id}",
|
"quotes/{id}", VendorCtrl::getQuotes, Roles(Role.Explicit("ROLE_QUOTE_VIEW", "ROLE_QUOTE_CREATE", "ROLE_VENDOR_VIEW"))
|
||||||
Vendor::getQuotes,
|
|
||||||
Roles(
|
|
||||||
Role.Explicit(
|
|
||||||
listOf(
|
|
||||||
"ROLE_ADMIN",
|
|
||||||
"ROLE_QUOTE_VIEW",
|
|
||||||
"ROLE_QUOTE_CREATE",
|
|
||||||
"ROLE_VENDOR_VIEW"
|
|
||||||
)
|
)
|
||||||
)
|
get("pos/{id}", VendorCtrl::getPos, Roles(Role.Explicit("ROLE_PO_VIEW", "ROLE_PO_CREATE`")))
|
||||||
)
|
put("/rate/{id}/{rating}", VendorCtrl::rate, Roles(Role.Explicit("ROLE_VENDOR_CREATE")))
|
||||||
)
|
put("/{id}", VendorCtrl::update, Roles(Role.Explicit("ROLE_VENDOR_CREATE")))
|
||||||
get(
|
|
||||||
"pos/{id}",
|
|
||||||
Vendor::getPos,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_PO_VIEW", "ROLE_PO_CREATE`")))
|
|
||||||
)
|
|
||||||
put("/rate/{id}/{rating}", Vendor::rate, Roles(Role.Explicit(listOf("ROLE_VENDOR_CREATE"))))
|
|
||||||
}
|
}
|
||||||
path("/po") {
|
path("/incoming") {
|
||||||
post("", PurchaseOrder::create, Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_ADMIN"))))
|
|
||||||
get(
|
get(
|
||||||
"/{id}",
|
"/plants", IncomingInventoryCtrl::plantsForUser
|
||||||
PurchaseOrder::get,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_QUOTE_CREATE")))
|
|
||||||
)
|
)
|
||||||
put(
|
put(
|
||||||
"/approve/{id}",
|
"/plants/{id}", IncomingInventoryCtrl::updatePlant,
|
||||||
PurchaseOrder::approve,
|
Roles(
|
||||||
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_APPROVE")))
|
Role.Explicit("ROLE_INVENTORY_CREATE"),
|
||||||
|
Role.Explicit("ROLE_VENDOR_CREATE")
|
||||||
)
|
)
|
||||||
put(
|
|
||||||
"/reject/{id}",
|
|
||||||
PurchaseOrder::reject,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_APPROVE")))
|
|
||||||
)
|
)
|
||||||
|
post("", IncomingInventoryCtrl::create, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
|
||||||
|
get("/next", IncomingInventoryCtrl::getNextNum, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
|
||||||
get(
|
get(
|
||||||
"/refQuote/{id}",
|
"/{id}", IncomingInventoryCtrl::get, Roles(Role.Explicit("ROLE_INVENTORY_VIEW", "ROLE_INVENTORY_CREATE"))
|
||||||
PurchaseOrder::quoteReference,
|
)
|
||||||
Roles(Role.Explicit(listOf("ROLE_PO_CREATE", "ROLE_PO_VIEW")))
|
put("/{id}", IncomingInventoryCtrl::update, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", IncomingInventoryCtrl::getAll, Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW"))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
path("/quote") {
|
path("/outgoing") {
|
||||||
post("", Quotation::create, Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN"))))
|
post("", OutgoingInventoryCtrl::create, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
|
||||||
|
get("/next", OutgoingInventoryCtrl::getNextNum, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
|
||||||
get(
|
get(
|
||||||
"/{id}",
|
"/{id}", OutgoingInventoryCtrl::get, Roles(Role.Explicit("ROLE_INVENTORY_VIEW", "ROLE_INVENTORY_CREATE"))
|
||||||
Quotation::get,
|
)
|
||||||
Roles(
|
put("/{id}", OutgoingInventoryCtrl::update, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", OutgoingInventoryCtrl::getAll, Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
path("/invoice") {
|
||||||
|
post("", InvoiceCtrl::create, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
|
||||||
|
get("/next", InvoiceCtrl::getNextNum, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
|
||||||
|
get(
|
||||||
|
"/{id}", InvoiceCtrl::get, Roles(Role.Explicit("ROLE_INVOICE_VIEW", "ROLE_INVOICE_CREATE"))
|
||||||
|
)
|
||||||
|
put("/{id}", InvoiceCtrl::update, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", InvoiceCtrl::getAll, Roles(Role.Explicit("ROLE_INVOICE_CREATE", "ROLE_INVOICE_VIEW"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
path("/payment") {
|
||||||
|
post("", PaymentCtrl::create, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
|
||||||
|
get(
|
||||||
|
"/{id}", PaymentCtrl::get, Roles(Role.Explicit("ROLE_PAYMENT_VIEW", "ROLE_PAYMENT_CREATE"))
|
||||||
|
)
|
||||||
|
put("/{id}", PaymentCtrl::update, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", PaymentCtrl::getAll, Roles(Role.Explicit("ROLE_PAYMENT_CREATE", "ROLE_PAYMENT_VIEW"))
|
||||||
|
)
|
||||||
|
delete("/{id}", PaymentCtrl::delete, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
|
||||||
|
}
|
||||||
|
path("/fleet") {
|
||||||
|
|
||||||
|
post("", FleetCtrl::create, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
get(
|
||||||
|
"/{id}", FleetCtrl::get, Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
|
||||||
|
)
|
||||||
|
put("/{id}", FleetCtrl::update, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", FleetCtrl::getAll, Roles(
|
||||||
Role.Explicit(
|
Role.Explicit(
|
||||||
listOf(
|
"ROLE_FLEET_CREATE",
|
||||||
"ROLE_QUOTE_VIEW",
|
"ROLE_FLEET_VIEW",
|
||||||
"ROLE_ADMIN",
|
"ROLE_EXPENSE_CREATE",
|
||||||
"ROLE_PO_CREATE",
|
"ROLE_EXPENSE_VIEW",
|
||||||
"ROLE_QUOTE_CREATE"
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
delete("/{id}", FleetCtrl::delete, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
}
|
||||||
|
path("/renewal") {
|
||||||
|
post("", RenewalCtrl::create, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
get(
|
||||||
|
"/{id}", RenewalCtrl::get, Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
|
||||||
|
)
|
||||||
|
put("/{id}", RenewalCtrl::update, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", RenewalCtrl::getAll, Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
|
||||||
|
)
|
||||||
|
delete("/{id}", RenewalCtrl::delete, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
}
|
||||||
|
path("/reminder") {
|
||||||
|
post("", ReminderCtrl::create, Roles(Role.Explicit("ROLE_REMINDER_CREATE")))
|
||||||
|
get(
|
||||||
|
"/{id}", ReminderCtrl::get, Roles(Role.Explicit("ROLE_REMINDER_VIEW", "ROLE_REMINDER_CREATE"))
|
||||||
|
)
|
||||||
|
put("/{id}", ReminderCtrl::update, Roles(Role.Explicit("ROLE_REMINDER_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", ReminderLogCtrl::getAll, Roles(Role.Explicit("ROLE_REMINDER_CREATE", "ROLE_REMINDER_VIEW"))
|
||||||
|
)
|
||||||
|
post(
|
||||||
|
"/done", ReminderLogCtrl::done, Roles(Role.Explicit("ROLE_REMAINDER_CREATE"))
|
||||||
)
|
)
|
||||||
get(
|
get(
|
||||||
"/po/{id}",
|
"/getAll/{id}", ReminderCtrl::getAllByFleetId, Roles(Role.Explicit("ROLE_REMINDER_CREATE", "ROLE_REMINDER_VIEW"))
|
||||||
Quotation::generatePO,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_ADMIN", "ROLE_PO_CRETE")))
|
|
||||||
)
|
|
||||||
get(
|
|
||||||
"/rfq/{rfqNum}",
|
|
||||||
Quotation::reqForQuote,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_QUOTE_VIEW")))
|
|
||||||
)
|
)
|
||||||
delete(
|
delete(
|
||||||
"/{id}",
|
"/{id}", ReminderCtrl::delete, Roles(Role.Explicit("ROLE_REMINDER_CREATE"))
|
||||||
Quotation::delete,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_QUOTE_CREATE", "ROLE_ADMIN")))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
path("/fleetType") {
|
||||||
|
post("", FleetTypeCtrl::create, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
get(
|
||||||
|
"/{id}", FleetTypeCtrl::get, Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
|
||||||
|
)
|
||||||
|
put("/{id}", FleetTypeCtrl::update, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", FleetTypeCtrl::getAll, Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
path("/po") {
|
||||||
|
get("/next", PurchaseOrderCtrl::getNextNum, Roles(Role.Explicit("ROLE_PO_CREATE")))
|
||||||
|
post("", PurchaseOrderCtrl::create, Roles(Role.Explicit("ROLE_PO_CREATE")))
|
||||||
|
post("/batch", PurchaseOrderCtrl::createBatch, Roles(Role.Explicit("ROLE_PO_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", PurchaseOrderCtrl::getAll, Roles(Role.Explicit("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_VENDOR_CREATE"))
|
||||||
|
)
|
||||||
|
get(
|
||||||
|
"/{id}", PurchaseOrderCtrl::get, Roles(Role.Explicit("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_QUOTE_CREATE"))
|
||||||
|
)
|
||||||
|
put("/{id}", PurchaseOrderCtrl::update, Roles(Role.Explicit("ROLE_PO_CREATE")))
|
||||||
|
put("/approve/{id}", PurchaseOrderCtrl::approve, Roles(Role.Explicit()))
|
||||||
|
put("/reject/{id}", PurchaseOrderCtrl::reject, Roles(Role.Explicit()))
|
||||||
|
get("/refQuote/{id}", PurchaseOrderCtrl::quoteReference, Roles(Role.Explicit("ROLE_PO_CREATE")))
|
||||||
|
}
|
||||||
|
path("/quote") {
|
||||||
|
get("/next", QuotationCtrl::getNextNum, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
|
||||||
|
post("", QuotationCtrl::create, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
|
||||||
|
post("/batch", QuotationCtrl::createBatch, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
|
||||||
|
post(
|
||||||
|
"/getAll", QuotationCtrl::getAll, Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_QUOTE_VIEW"))
|
||||||
|
)
|
||||||
|
get("/{id}", QuotationCtrl::get, Roles(Role.Explicit("ROLE_QUOTE_VIEW", "ROLE_QUOTE_CREATE")))
|
||||||
|
put("/{id}", QuotationCtrl::update, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
|
||||||
|
delete("/{id}", QuotationCtrl::delete, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
|
||||||
|
}
|
||||||
path("/product") {
|
path("/product") {
|
||||||
post("", ProductCtrl::create, Roles(Role.Explicit(listOf("ROLE_PRODUCT_CREATE", "ROLE_ADMIN"))))
|
post("", ProductCtrl::create, Roles(Role.Explicit("ROLE_PRODUCT_CREATE")))
|
||||||
get("/{hsnCode}", ProductCtrl::get, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
|
put("/{id}", ProductCtrl::update, Roles(Role.Explicit("ROLE_PRODUCT_CREATE")))
|
||||||
patch("/{id}", ProductCtrl::patch, Roles(Role.Explicit(listOf("ROLE_PRODUCT_UPDATE", "ROLE_ADMIN"))))
|
delete("/{id}", ProductCtrl::delete, Roles(Role.Explicit("ROLE_PRODUCT_CREATE")))
|
||||||
put("/{id}", ProductCtrl::update, Roles(Role.Explicit(listOf("ROLE_PRODUCT_UPDATE", "ROLE_ADMIN"))))
|
patch("/{id}", ProductCtrl::patch, Roles(Role.Explicit("ROLE_PRODUCT_CREATE")))
|
||||||
delete("/{id}", ProductCtrl::delete, Roles(Role.Explicit(listOf("ROLE_PRODUCT_DELETE", "ROLE_ADMIN"))))
|
post("/getPrice", ProductCtrl::getPrice, Roles(Role.Explicit("ROLE_PRODUCT_VIEW")))
|
||||||
get("", ProductCtrl::getAll, Roles(Role.Explicit(listOf("ROLE_PRODUCT_VIEW", "ROLE_ADMIN"))))
|
post("/getAll", ProductCtrl::getAll, Roles(Role.Explicit("ROLE_PRODUCT_VIEW")))
|
||||||
post("/product-excel", ProductCtrl::prodExcel)
|
get("/{id}", ProductCtrl::get, Roles(Role.Explicit("ROLE_PRODUCT_VIEW")))
|
||||||
post("/import") {ctx -> ctx.json(excelToDb())}
|
|
||||||
}
|
}
|
||||||
path("/doc") {
|
path("/doc") {
|
||||||
post("", Document::create, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE", "ROLE_ADMIN"))))
|
post("", DocumentCtrl::create, Roles(Role.Explicit("ROLE_DOC_CREATE")))
|
||||||
//why type and refid are clubbed ??
|
//why type and refid are clubbed ??
|
||||||
get(
|
get(
|
||||||
"/{type}/{refId}",
|
"/{type}/{refId}", DocumentCtrl::getWithRefId, Roles(Role.Explicit("ROLE_DOC_VIEW", "ROLE_PRODUCT_CREATE"))
|
||||||
Document::getWithRefId,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_DOC_VIEW", "ROLE_ADMIN", "ROLE_PRODUCT_CREATE")))
|
|
||||||
)
|
)
|
||||||
|
get("/{id}", DocumentCtrl::get, Roles(Role.Explicit("ROLE_DOC_VIEW", "ROLE_PRODUCT_CREATE")))
|
||||||
get(
|
get(
|
||||||
"/{id}",
|
"/print/{id}", DocumentCtrl::print, Roles(Role.Explicit("ROLE_DOC_CREATE", "ROLE_DOC_VIEW"))
|
||||||
Document::get,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_DOC_VIEW", "ROLE_ADMIN", "ROLE_PRODUCT_CREATE")))
|
|
||||||
)
|
)
|
||||||
get(
|
delete("/{id}", DocumentCtrl::delete, Roles(Role.Explicit("ROLE_DOC_CREATE")))
|
||||||
"/print/{id}",
|
|
||||||
Document::print,
|
|
||||||
Roles(Role.Explicit(listOf("ROLE_DOC_CREATE", "ROLE_DOC_VIEW")))
|
|
||||||
)
|
|
||||||
delete("/{id}", Document::delete, Roles(Role.Explicit(listOf("ROLE_DOC_CREATE"))))
|
|
||||||
}
|
}
|
||||||
path("/reqForQuote") {
|
path("/reqForQuote") {
|
||||||
post("", RequestForQuote::create, Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE"))))
|
post(
|
||||||
get(
|
"", RequestForQuote::create, Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_PO_CREATE", "ROLE_RFQ_CREATE"))
|
||||||
"/{id}",
|
)
|
||||||
RequestForQuote::get,
|
get(
|
||||||
Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE", "ROLE_RFQ_VIEW")))
|
"/{id}", RequestForQuote::get, Roles(Role.Explicit("ROLE_RFQ_CREATE", "ROLE_RFQ_VIEW", "ROLE_QUOTE_VIEW", "ROLE_PO_VIEW"))
|
||||||
|
)
|
||||||
|
put(
|
||||||
|
"/{id}", RequestForQuote::update, Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_PO_CREATE", "ROLE_RFQ_CREATE"))
|
||||||
)
|
)
|
||||||
put("/{id}", RequestForQuote::update, Roles(Role.Explicit(listOf("ROLE_RFQ_CREATE"))))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
post("/script/database/{name}", Entities::executeStoredProcedure, Roles(adminRole, Role.DbOps))
|
|
||||||
post("/script/{file}/{name}", Entities::executeScript, Roles(adminRole, Role.DbOps))
|
|
||||||
|
|
||||||
get("/{entity}/{id}", Entities::view, Roles(adminRole, viewRole))
|
get("/{entity}", Entities::getAll)
|
||||||
post("/{entity}/query/{id}", Entities::sqlQueryById, Roles(adminRole, viewRole))
|
post("/{entity}/next", Entities::getNextSeqNo, Roles(adminRole, viewRole, appAdmin))
|
||||||
post("/{entity}/query", Entities::sqlQueryRaw, Roles(adminRole, viewRole))
|
get("/{entity}/{id}", Entities::view, Roles(adminRole, viewRole, appAdmin))
|
||||||
post("/{entity}", Entities::create, Roles(adminRole, createRole))
|
post("/{entity}/search", Entities::search, Roles(adminRole, viewRole, appAdmin))
|
||||||
|
post("/{entity}", Entities::create, Roles(adminRole, createRole, appAdmin))
|
||||||
|
|
||||||
put("/{entity}/approve/{id}", Entities::approve, Roles(adminRole, approveOrRejectRole))
|
|
||||||
put("/{entity}/reject/{id}", Entities::reject, Roles(adminRole, approveOrRejectRole))
|
|
||||||
put("/{entity}/{action}/{id}", Entities::action, Roles(adminRole, Role.Entity))
|
|
||||||
|
|
||||||
put("/{entity}/{id}", Entities::update, Roles(adminRole, updateRole))
|
put("/{entity}/{id}", Entities::update, Roles(adminRole, updateRole, appAdmin))
|
||||||
patch("/{entity}/{id}", Entities::patch, Roles(adminRole, updateRole))
|
patch("/{entity}/{id}", Entities::patch, Roles(adminRole, updateRole, appAdmin))
|
||||||
delete("/{entity}/{id}", Entities::delete, Roles(adminRole, Role.Standard(Action.DELETE)))
|
delete("/{entity}/{id}", Entities::delete, Roles(adminRole, Role.Standard(Action.DELETE), appAdmin))
|
||||||
}
|
}
|
||||||
}
|
}.exception(DuplicateKeyException::class.java, Exceptions.dupKeyExceptionHandler)
|
||||||
.exception(DuplicateKeyException::class.java, Exceptions.dupKeyExceptionHandler)
|
|
||||||
.exception(DataIntegrityException::class.java, Exceptions.dataIntegrityException)
|
.exception(DataIntegrityException::class.java, Exceptions.dataIntegrityException)
|
||||||
.exception(DataNotFoundException::class.java, Exceptions.dataNotFoundException)
|
.exception(DataNotFoundException::class.java, Exceptions.dataNotFoundException)
|
||||||
.exception(IllegalArgumentException::class.java, Exceptions.illegalArgumentException)
|
.exception(IllegalArgumentException::class.java, Exceptions.illegalArgumentException)
|
||||||
.exception(JsonMappingException::class.java, Exceptions.jsonMappingException)
|
.exception(JsonMappingException::class.java, Exceptions.jsonMappingException)
|
||||||
.exception(InvalidJwtException::class.java, Exceptions.invalidJwtException)
|
.exception(InvalidJwtException::class.java, Exceptions.invalidJwtException).start(appConfig.portNumber())
|
||||||
.start(appConfig.portNumber())
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun Context.getAuthHeader() = header("Authorization")
|
private fun Context.getAuthHeader() = header("Authorization")?.replace("Bearer ", "")?.replace("Bearer: ", "")?.trim()
|
||||||
?.replace("Bearer ", "")
|
|
||||||
?.replace("Bearer: ", "")
|
|
||||||
?.trim()
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ import net.cactusthorn.config.core.loader.LoadStrategy
|
|||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
|
|
||||||
@Config(
|
@Config(
|
||||||
sources = ["file:~/app.yaml", "system:env"],
|
sources = [
|
||||||
|
"file:./app.properties",
|
||||||
|
"file:~/app.properties",
|
||||||
|
"file:./app.yaml",
|
||||||
|
"file:~/app.yaml",
|
||||||
|
"system:env",
|
||||||
|
],
|
||||||
loadStrategy = LoadStrategy.FIRST_KEYCASEINSENSITIVE
|
loadStrategy = LoadStrategy.FIRST_KEYCASEINSENSITIVE
|
||||||
)
|
)
|
||||||
interface AppConfig {
|
interface AppConfig {
|
||||||
@@ -58,6 +64,10 @@ interface AppConfig {
|
|||||||
@Key("app.iam.client_secret")
|
@Key("app.iam.client_secret")
|
||||||
fun iamClientSecret(): Optional<String>
|
fun iamClientSecret(): Optional<String>
|
||||||
|
|
||||||
|
@Key("app.integration.rmc")
|
||||||
|
@Default("https://www.readymixerp.com")
|
||||||
|
fun integrationRmc(): String
|
||||||
|
|
||||||
@Key("app.cache.redis_uri")
|
@Key("app.cache.redis_uri")
|
||||||
fun redisUri(): Optional<String>
|
fun redisUri(): Optional<String>
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,20 @@ package com.restapi.config
|
|||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.restapi.config.AppConfig.Companion.appConfig
|
import com.restapi.config.AppConfig.Companion.appConfig
|
||||||
|
import com.restapi.domain.AuthTokenCache
|
||||||
|
import com.restapi.domain.Plant
|
||||||
|
import com.restapi.domain.RefreshHistory
|
||||||
import com.restapi.domain.Session
|
import com.restapi.domain.Session
|
||||||
|
import com.restapi.domain.Session.database
|
||||||
import com.restapi.domain.Session.objectMapper
|
import com.restapi.domain.Session.objectMapper
|
||||||
import io.javalin.http.BadRequestResponse
|
import io.javalin.http.BadRequestResponse
|
||||||
import io.javalin.http.ContentType
|
import io.javalin.http.ContentType
|
||||||
import io.javalin.http.Context
|
import io.javalin.http.Context
|
||||||
import io.javalin.http.UnauthorizedResponse
|
import io.javalin.http.UnauthorizedResponse
|
||||||
import io.javalin.security.RouteRole
|
import io.javalin.security.RouteRole
|
||||||
|
import org.apache.http.client.methods.HttpGet
|
||||||
|
import org.apache.http.impl.client.HttpClients
|
||||||
|
import org.apache.http.util.EntityUtils
|
||||||
import org.jose4j.jwk.HttpsJwks
|
import org.jose4j.jwk.HttpsJwks
|
||||||
import org.jose4j.jwt.consumer.JwtConsumerBuilder
|
import org.jose4j.jwt.consumer.JwtConsumerBuilder
|
||||||
import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver
|
import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver
|
||||||
@@ -21,12 +28,11 @@ import java.net.http.HttpResponse
|
|||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
|
||||||
const val AUTH_TOKEN = "AUTH_TOKEN_V2"
|
|
||||||
|
|
||||||
private fun getFormDataAsString(formData: Map<String, String>): String {
|
private fun getFormDataAsString(formData: Map<String, String>): String {
|
||||||
|
|
||||||
return formData.entries.joinToString("&") {
|
return formData.entries.joinToString("&") {
|
||||||
@@ -41,15 +47,12 @@ object Auth {
|
|||||||
private val logger = LoggerFactory.getLogger("Auth")
|
private val logger = LoggerFactory.getLogger("Auth")
|
||||||
private val authCache = ConcurrentHashMap<String, AuthEndpoint>()
|
private val authCache = ConcurrentHashMap<String, AuthEndpoint>()
|
||||||
|
|
||||||
fun getAuthEndpoint(): AuthEndpoint {
|
private fun getAuthEndpoint(): AuthEndpoint {
|
||||||
return authCache.computeIfAbsent("AUTH") {
|
return authCache.computeIfAbsent("AUTH") {
|
||||||
val wellKnown =
|
val wellKnown = "${appConfig.iamUrl()}/realms/${appConfig.iamRealm()}/.well-known/openid-configuration"
|
||||||
"${appConfig.iamUrl()}/realms/${appConfig.iamRealm()}/.well-known/openid-configuration"
|
|
||||||
val client = HttpClient.newHttpClient()
|
val client = HttpClient.newHttpClient()
|
||||||
|
|
||||||
val req = HttpRequest.newBuilder()
|
val req = HttpRequest.newBuilder().uri(URI.create(wellKnown)).GET().build()
|
||||||
.uri(URI.create(wellKnown))
|
|
||||||
.GET().build()
|
|
||||||
|
|
||||||
objectMapper.readValue<AuthEndpoint>(
|
objectMapper.readValue<AuthEndpoint>(
|
||||||
client.send(req, HttpResponse.BodyHandlers.ofString()).body()
|
client.send(req, HttpResponse.BodyHandlers.ofString()).body()
|
||||||
@@ -58,19 +61,15 @@ object Auth {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val jwtConsumer = JwtConsumerBuilder()
|
private val jwtConsumer =
|
||||||
.setRequireExpirationTime()
|
JwtConsumerBuilder().setRequireExpirationTime().setAllowedClockSkewInSeconds(30).setRequireSubject()
|
||||||
.setAllowedClockSkewInSeconds(30)
|
|
||||||
.setRequireSubject()
|
|
||||||
.setExpectedAudience("account")
|
.setExpectedAudience("account")
|
||||||
.setExpectedIssuer(getAuthEndpoint().issuer)
|
.setExpectedIssuer(getAuthEndpoint().issuer)
|
||||||
.setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri)))
|
.setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri))).build()
|
||||||
.build()
|
|
||||||
|
|
||||||
private val jwtConsumerSkipValidate = JwtConsumerBuilder()
|
private val jwtConsumerSkipValidate =
|
||||||
.setSkipAllValidators()
|
JwtConsumerBuilder().setSkipAllValidators()
|
||||||
.setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri)))
|
.setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri))).build()
|
||||||
.build()
|
|
||||||
|
|
||||||
fun validateAuthToken(authToken: String, skipValidate: Boolean = false): AuthUser {
|
fun validateAuthToken(authToken: String, skipValidate: Boolean = false): AuthUser {
|
||||||
|
|
||||||
@@ -78,17 +77,52 @@ object Auth {
|
|||||||
val jwtClaims = if (skipValidate) jwtConsumerSkipValidate.process(authToken) else jwtConsumer.process(authToken)
|
val jwtClaims = if (skipValidate) jwtConsumerSkipValidate.process(authToken) else jwtConsumer.process(authToken)
|
||||||
val userId = jwtClaims.jwtClaims.claimsMap["preferred_username"] as String
|
val userId = jwtClaims.jwtClaims.claimsMap["preferred_username"] as String
|
||||||
val tenant = jwtClaims.jwtClaims.claimsMap["tenant"] as String
|
val tenant = jwtClaims.jwtClaims.claimsMap["tenant"] as String
|
||||||
|
val plantIds = jwtClaims.jwtClaims.claimsMap["plantIds"] as List<String>
|
||||||
val roles = ((jwtClaims.jwtClaims.claimsMap["realm_access"] as Map<String, Any>)["roles"]) as List<String>
|
val roles = ((jwtClaims.jwtClaims.claimsMap["realm_access"] as Map<String, Any>)["roles"]) as List<String>
|
||||||
val date = Date(jwtClaims.jwtClaims.expirationTime.valueInMillis)
|
val date = Date(jwtClaims.jwtClaims.expirationTime.valueInMillis)
|
||||||
|
|
||||||
|
try {
|
||||||
|
HttpClients.createDefault().use { h ->
|
||||||
|
//sync plant's from rmc to here, just name and id
|
||||||
|
for (plantId in plantIds) {
|
||||||
|
|
||||||
|
val existing = database.find(Plant::class.java).where().eq("plantId", plantId).findOne()
|
||||||
|
|
||||||
|
h.execute(HttpGet("${appConfig.integrationRmc()}/plant?id=${plantId}")).use { r ->
|
||||||
|
if (r.statusLine.statusCode == 200) {
|
||||||
|
val response = EntityUtils.toString(r.entity)
|
||||||
|
if (existing == null) {
|
||||||
|
database.save(Plant().apply {
|
||||||
|
this.plantId = plantId
|
||||||
|
this.plantName = response
|
||||||
|
this.plantOriginalName = response
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
existing.apply {
|
||||||
|
this.plantOriginalName = response
|
||||||
|
this.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.warn("Exception in syncing plants", e)
|
||||||
|
}
|
||||||
|
|
||||||
return AuthUser(
|
return AuthUser(
|
||||||
userName = userId,
|
userName = userId,
|
||||||
tenant = tenant,
|
tenant = tenant,
|
||||||
roles = roles,
|
roles = roles,
|
||||||
token = authToken,
|
token = authToken,
|
||||||
expiry = LocalDateTime.from(date.toInstant().atZone(ZoneId.systemDefault()))
|
expiry = LocalDateTime.from(date.toInstant().atZone(ZoneId.systemDefault())),
|
||||||
|
plantIds = plantIds
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val userToTenant = ConcurrentHashMap<String, String>()
|
||||||
|
|
||||||
fun keys(ctx: Context) {
|
fun keys(ctx: Context) {
|
||||||
ctx.json(Session.jwk())
|
ctx.json(Session.jwk())
|
||||||
}
|
}
|
||||||
@@ -112,9 +146,7 @@ object Auth {
|
|||||||
|
|
||||||
val ep = getAuthEndpoint().tokenEndpoint
|
val ep = getAuthEndpoint().tokenEndpoint
|
||||||
val httpClient = HttpClient.newHttpClient()
|
val httpClient = HttpClient.newHttpClient()
|
||||||
val req = HttpRequest.newBuilder()
|
val req = HttpRequest.newBuilder().uri(URI.create(ep)).POST(
|
||||||
.uri(URI.create(ep))
|
|
||||||
.POST(
|
|
||||||
HttpRequest.BodyPublishers.ofString(
|
HttpRequest.BodyPublishers.ofString(
|
||||||
getFormDataAsString(
|
getFormDataAsString(
|
||||||
mapOf(
|
mapOf(
|
||||||
@@ -125,61 +157,85 @@ object Auth {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
).header("Content-Type", "application/x-www-form-urlencoded").build()
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val message = httpClient.send(req, HttpResponse.BodyHandlers.ofString()).body()
|
val message = httpClient.send(req, HttpResponse.BodyHandlers.ofString()).body()
|
||||||
val atResponse = objectMapper.readValue<AuthTokenResponse>(message)
|
val atResponse = objectMapper.readValue<AuthTokenResponse>(message)
|
||||||
val parsed = validateAuthToken(atResponse.accessToken)
|
val parsed = validateAuthToken(atResponse.accessToken)
|
||||||
|
|
||||||
//keep track of this for renewal when asked by client
|
|
||||||
Session.redis.lpush(
|
database.save(AuthTokenCache().apply {
|
||||||
"$AUTH_TOKEN${parsed.userName}",
|
this.userId = parsed.userName
|
||||||
objectMapper.writeValueAsString(
|
this.authToken = atResponse.accessToken
|
||||||
atResponse.copy(
|
this.expiresAt = LocalDateTime.now().plusSeconds(atResponse.expiresIn.toLong())
|
||||||
createdAt = LocalDateTime.now()
|
this.refreshToken = atResponse.refreshToken
|
||||||
)
|
this.refreshExpiresAt = LocalDateTime.now().plusSeconds(atResponse.refreshExpiresIn.toLong())
|
||||||
)
|
this.refreshHistory = arrayListOf()
|
||||||
)
|
})
|
||||||
ctx.result(atResponse.accessToken).contentType(ContentType.TEXT_PLAIN)
|
ctx.result(atResponse.accessToken).contentType(ContentType.TEXT_PLAIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun logout(ctx: Context) {
|
||||||
|
val authToken = ctx.header("Authorization")?.replace("Bearer ", "")?.replace("Bearer: ", "")?.trim()
|
||||||
|
?: return
|
||||||
|
val authUser = validateAuthToken(authToken, skipValidate = true)
|
||||||
|
logger.warn("User ${authUser.userName} is logging out")
|
||||||
|
database.updateAll(
|
||||||
|
database.find(AuthTokenCache::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("authToken", authToken)
|
||||||
|
.findList()
|
||||||
|
.onEach {
|
||||||
|
it.loggedOut = true
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.json(mapOf("status" to true))
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshToken(ctx: Context) {
|
fun refreshToken(ctx: Context) {
|
||||||
//refresh authToken
|
//refresh authToken
|
||||||
val authToken = ctx.header("Authorization")
|
val authToken = ctx.header("Authorization")?.replace("Bearer ", "")?.replace("Bearer: ", "")?.trim()
|
||||||
?.replace("Bearer ", "")
|
?: throw UnauthorizedResponse()
|
||||||
?.replace("Bearer: ", "")
|
|
||||||
?.trim() ?: throw UnauthorizedResponse()
|
|
||||||
|
|
||||||
val authUser = validateAuthToken(authToken, skipValidate = true)
|
val authUser = validateAuthToken(authToken, skipValidate = true)
|
||||||
val client = ctx.queryParam("client") ?: throw BadRequestResponse("client not sent")
|
val client = ctx.queryParam("client") ?: throw BadRequestResponse("client not sent")
|
||||||
val redirectUri = ctx.queryParam("redirectUri") ?: throw BadRequestResponse("redirectUri not sent")
|
val redirectUri = ctx.queryParam("redirectUri") ?: throw BadRequestResponse("redirectUri not sent")
|
||||||
|
|
||||||
val key = "$AUTH_TOKEN${authUser.userName}"
|
val foundOldAt = database.find(AuthTokenCache::class.java)
|
||||||
val found = Session.redis.llen(key)
|
.where()
|
||||||
logger.warn("for user ${authUser.userName}, found from redis, $key => $found entries")
|
.eq("userId", authUser.userName)
|
||||||
val foundOldAt = (0..found)
|
.eq("expired", false)
|
||||||
.mapNotNull { Session.redis.lindex(key, it) }
|
.eq("loggedOut", false)
|
||||||
.map { objectMapper.readValue<AuthTokenResponse>(it) }
|
.gt("refreshExpiresAt", LocalDateTime.now())
|
||||||
.firstOrNull { it.accessToken == authToken }
|
.findList()
|
||||||
?: throw BadRequestResponse("authToken not found in cache")
|
.onEach {
|
||||||
|
logger.warn("valid authToken for ${authUser.userName} is ${it.authToken.substring(0..10)}")
|
||||||
|
}
|
||||||
|
.firstOrNull {
|
||||||
|
it.authToken.equals(authToken, ignoreCase = true)
|
||||||
|
} ?: throw BadRequestResponse("we did not find an entry for this auth token $authToken")
|
||||||
|
|
||||||
val createdAt = foundOldAt.createdAt ?: throw BadRequestResponse("created at is missing")
|
val createdAt = foundOldAt.createdAt
|
||||||
val expiresAt = createdAt.plusSeconds(foundOldAt.expiresIn + 0L)
|
val expiresAt = foundOldAt.expiresAt
|
||||||
val rtExpiresAt = createdAt.plusSeconds(foundOldAt.refreshExpiresIn + 0L)
|
val rtExpiresAt = foundOldAt.refreshExpiresAt
|
||||||
|
|
||||||
val now = LocalDateTime.now()
|
val now = LocalDateTime.now()
|
||||||
logger.warn("can we refresh the token for ${authUser.userName}, created = $createdAt expires = $expiresAt, refresh Till = $rtExpiresAt")
|
logger.warn("can we refresh the token for ${authUser.userName}, created = $createdAt expires = $expiresAt, refresh Till = $rtExpiresAt")
|
||||||
|
|
||||||
|
val authTokenValid = expiresAt.isAfter(now)
|
||||||
|
if (authTokenValid) {
|
||||||
|
ctx.result(authToken).contentType(ContentType.TEXT_PLAIN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
//we can refresh if at is expired, but we still have time for refresh
|
//we can refresh if at is expired, but we still have time for refresh
|
||||||
if (expiresAt.isBefore(now) && now.isBefore(rtExpiresAt)) {
|
val refreshTokenValid = rtExpiresAt.isAfter(now)
|
||||||
|
if (refreshTokenValid) {
|
||||||
logger.warn("We can refresh the token for ${authUser.userName}, expires = $expiresAt, refresh Till = $rtExpiresAt")
|
logger.warn("We can refresh the token for ${authUser.userName}, expires = $expiresAt, refresh Till = $rtExpiresAt")
|
||||||
val ep = getAuthEndpoint().tokenEndpoint
|
val ep = getAuthEndpoint().tokenEndpoint
|
||||||
val httpClient = HttpClient.newHttpClient()
|
val httpClient = HttpClient.newHttpClient()
|
||||||
val req = HttpRequest.newBuilder()
|
val req = HttpRequest.newBuilder().uri(URI.create(ep)).POST(
|
||||||
.uri(URI.create(ep))
|
|
||||||
.POST(
|
|
||||||
HttpRequest.BodyPublishers.ofString(
|
HttpRequest.BodyPublishers.ofString(
|
||||||
getFormDataAsString(
|
getFormDataAsString(
|
||||||
mapOf(
|
mapOf(
|
||||||
@@ -190,33 +246,33 @@ object Auth {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
).header("Content-Type", "application/x-www-form-urlencoded").build()
|
||||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
.build()
|
|
||||||
val message = httpClient.send(req, HttpResponse.BodyHandlers.ofString()).body()
|
val message = httpClient.send(req, HttpResponse.BodyHandlers.ofString()).body()
|
||||||
val atResponse = objectMapper.readValue<AuthTokenResponse>(message)
|
val atResponse = objectMapper.readValue<AuthTokenResponse>(message)
|
||||||
val parsed = validateAuthToken(atResponse.accessToken)
|
|
||||||
|
|
||||||
Session.redis.lpush(
|
foundOldAt.authToken = atResponse.accessToken
|
||||||
"AUTH_TOKEN_${parsed.userName}",
|
foundOldAt.expiresAt = LocalDateTime.now().plusSeconds(atResponse.expiresIn.toLong())
|
||||||
objectMapper.writeValueAsString(
|
foundOldAt.refreshExpiresAt = LocalDateTime.now().plusSeconds(atResponse.refreshExpiresIn.toLong())
|
||||||
atResponse.copy(createdAt = LocalDateTime.now())
|
foundOldAt.refreshToken = atResponse.refreshToken
|
||||||
)
|
foundOldAt.refreshHistory = (foundOldAt.refreshHistory ?: arrayListOf()).apply {
|
||||||
)
|
add(RefreshHistory().apply {
|
||||||
|
oldAt = authUser.token
|
||||||
|
oldExpiryAt = expiresAt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||||
|
newAt = atResponse.accessToken
|
||||||
|
newExpiryAt = LocalDateTime.now().plusSeconds(atResponse.expiresIn.toLong()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||||
|
this.createdAt = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
database.update(foundOldAt)
|
||||||
|
|
||||||
ctx.result(atResponse.accessToken).contentType(ContentType.TEXT_PLAIN)
|
ctx.result(atResponse.accessToken).contentType(ContentType.TEXT_PLAIN)
|
||||||
} else {
|
} else {
|
||||||
//at is still valid
|
//at is still valid
|
||||||
if (expiresAt.isAfter(now)) {
|
|
||||||
logger.warn("Still valid, the token for ${authUser.userName}, will expire at $expiresAt")
|
|
||||||
ctx.result(foundOldAt.accessToken).contentType(ContentType.TEXT_PLAIN)
|
|
||||||
} else {
|
|
||||||
//we have exceeded the refresh time, so we shall ask the user to login again
|
//we have exceeded the refresh time, so we shall ask the user to login again
|
||||||
logger.warn("We can't refresh the token for ${authUser.userName}, as refresh-time [$rtExpiresAt] is expired")
|
logger.warn("We can't refresh the token for ${authUser.userName}, as refresh-time [$rtExpiresAt] is expired")
|
||||||
throw UnauthorizedResponse()
|
throw UnauthorizedResponse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +281,8 @@ data class AuthUser(
|
|||||||
val tenant: String,
|
val tenant: String,
|
||||||
val roles: List<String>,
|
val roles: List<String>,
|
||||||
val token: String,
|
val token: String,
|
||||||
val expiry: LocalDateTime
|
val expiry: LocalDateTime,
|
||||||
|
val plantIds: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class Action {
|
enum class Action {
|
||||||
@@ -235,7 +292,7 @@ enum class Action {
|
|||||||
sealed class Role {
|
sealed class Role {
|
||||||
open class Standard(vararg val action: Action) : Role()
|
open class Standard(vararg val action: Action) : Role()
|
||||||
data object Entity : Role()
|
data object Entity : Role()
|
||||||
data class Explicit(val roles: List<String>) : Role()
|
open class Explicit(vararg val roles: String) : Role()
|
||||||
data object DbOps : Role()
|
data object DbOps : Role()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.restapi.controllers
|
||||||
|
|
||||||
|
import com.restapi.domain.DocType
|
||||||
|
import com.restapi.domain.Document
|
||||||
|
import com.restapi.domain.Session
|
||||||
|
import io.javalin.http.Context
|
||||||
|
import io.javalin.http.HttpStatus
|
||||||
|
import io.javalin.http.NotFoundResponse
|
||||||
|
import io.javalin.http.bodyAsClass
|
||||||
|
|
||||||
|
object DocumentCtrl {
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val doc = Session.database.find(Document::class.java, id) ?: throw NotFoundResponse("no doc found with id $id")
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
ctx.json(doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val doc = ctx.bodyAsClass<Document>()
|
||||||
|
Session.database.save(doc)
|
||||||
|
ctx.status(HttpStatus.CREATED)
|
||||||
|
ctx.json(doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun print(ctx: Context) {
|
||||||
|
//would be handled in the frontend ??
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val doc = Session.database.find(Document::class.java, id) ?: throw NotFoundResponse("no document found with id $id")
|
||||||
|
Session.database.delete(doc)
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getWithRefId(ctx: Context) {
|
||||||
|
//fetches a particular doc (po, quote) with ref id
|
||||||
|
val refId = ctx.pathParam("refId")
|
||||||
|
val doc = Session.database.find(Document::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("typeOfDoc", DocType.valueOf(ctx.pathParam("type")))
|
||||||
|
.eq("refIdOfDoc", refId)
|
||||||
|
?: throw NotFoundResponse("no doc found for refId $refId")
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
ctx.json(doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,110 +6,114 @@ import com.fasterxml.jackson.databind.JsonDeserializer
|
|||||||
import com.fasterxml.jackson.databind.JsonNode
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||||
import com.restapi.domain.*
|
import com.restapi.domain.*
|
||||||
import com.restapi.domain.Product
|
import com.restapi.domain.Session.currentRoles
|
||||||
import com.restapi.domain.PurchaseOrder
|
|
||||||
import com.restapi.domain.Quotation
|
|
||||||
import com.restapi.domain.Session.currentUser
|
import com.restapi.domain.Session.currentUser
|
||||||
import com.restapi.domain.Session.database
|
import com.restapi.domain.Session.database
|
||||||
import com.restapi.domain.Session.findDataModelByEntityAndUniqId
|
import com.restapi.domain.Session.findDataModelByEntityAndUniqId
|
||||||
import com.restapi.domain.Vendor
|
import com.restapi.domain.Session.objectMapper
|
||||||
import com.restapi.integ.Scripting
|
import com.restapi.integ.Scripting
|
||||||
import io.ebean.CallableSql
|
|
||||||
import io.ebean.RawSqlBuilder
|
import io.ebean.RawSqlBuilder
|
||||||
import io.javalin.http.*
|
import io.javalin.http.BadRequestResponse
|
||||||
import org.apache.poi.ss.usermodel.Cell
|
import io.javalin.http.Context
|
||||||
import org.apache.poi.ss.usermodel.CellType
|
import io.javalin.http.HttpStatus
|
||||||
import org.apache.poi.ss.usermodel.WorkbookFactory
|
import io.javalin.http.bodyAsClass
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.sql.Types
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.format.DateTimeParseException
|
||||||
|
|
||||||
enum class QueryParamType {
|
enum class QueryParamType {
|
||||||
STRING, NUMBER, DATETIME, DATE
|
STRING, NUMBER, DATETIME, DATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class RawQuery(
|
@JsonDeserialize(using = QueryParamDeSerializer::class)
|
||||||
val sql: String,
|
|
||||||
val params: Map<String, QueryParam>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class QueryById(
|
|
||||||
val params: List<QueryParam>
|
|
||||||
)
|
|
||||||
|
|
||||||
@JsonDeserialize(using = QueryByIdParamsDeSerializer::class)
|
|
||||||
sealed class QueryParam {
|
sealed class QueryParam {
|
||||||
data class Simple(val simple: String) : QueryParam()
|
data class StrParam(val str: String) : QueryParam()
|
||||||
data class Complex(val type: QueryParamType, val value: String) : QueryParam() {
|
data class NumberParam(val nbr: Number) : QueryParam()
|
||||||
|
data class BooleanParam(val bool: Boolean) : QueryParam()
|
||||||
|
data class ComplexParam(val type: QueryParamType, val value: String) : QueryParam() {
|
||||||
fun getValueComplex(): Any {
|
fun getValueComplex(): Any {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
QueryParamType.STRING -> value
|
QueryParamType.STRING -> value
|
||||||
QueryParamType.NUMBER -> if (value.matches(Regex("\\d+"))) value.toLong() else value.toDouble()
|
QueryParamType.NUMBER -> (if (value.matches(Regex("\\d+"))) value.toLongOrNull() else value.toDoubleOrNull())
|
||||||
QueryParamType.DATETIME -> LocalDateTime.parse(
|
?: throw IllegalArgumentException("$value is not a number")
|
||||||
|
|
||||||
|
QueryParamType.DATETIME -> try {
|
||||||
|
LocalDateTime.parse(
|
||||||
value,
|
value,
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||||
)
|
)
|
||||||
|
} catch (e: DateTimeParseException) {
|
||||||
|
throw IllegalArgumentException("unable to parse $value as datetime")
|
||||||
|
}
|
||||||
|
|
||||||
QueryParamType.DATE -> LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
|
QueryParamType.DATE -> try {
|
||||||
|
LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
|
||||||
|
} catch (e: DateTimeParseException) {
|
||||||
|
throw IllegalArgumentException("unable to parse $value as date")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getValue(): Any {
|
fun getValue(): Any {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is Complex -> getValueComplex()
|
is ComplexParam -> getValueComplex()
|
||||||
is Simple -> simple
|
is StrParam -> str
|
||||||
|
is NumberParam -> nbr
|
||||||
|
is BooleanParam -> bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class QueryByIdParamsDeSerializer : JsonDeserializer<QueryParam>() {
|
class QueryParamDeSerializer : JsonDeserializer<QueryParam>() {
|
||||||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): QueryParam {
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): QueryParam {
|
||||||
val node = p.readValueAsTree<JsonNode>()
|
val node = p.readValueAsTree<JsonNode>()
|
||||||
return if (node.isTextual) {
|
return if (node.isTextual) {
|
||||||
QueryParam.Simple(node.asText())
|
QueryParam.StrParam(node.asText())
|
||||||
} else {
|
} else if (node.isNumber) {
|
||||||
QueryParam.Complex(
|
QueryParam.NumberParam(node.numberValue())
|
||||||
|
} else if (node.isBoolean) {
|
||||||
|
QueryParam.BooleanParam(node.booleanValue())
|
||||||
|
} else if (node.isObject) {
|
||||||
|
QueryParam.ComplexParam(
|
||||||
QueryParamType.valueOf(node.get("type").textValue()),
|
QueryParamType.valueOf(node.get("type").textValue()),
|
||||||
node.get("value").textValue(),
|
node.get("value").textValue(),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
throw BadRequestResponse("unable to find valid query param for $node")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ResultType {
|
|
||||||
INTEGER, DECIMAL, STRING, DATETIME, ARRAY, OBJECT
|
|
||||||
}
|
|
||||||
|
|
||||||
data class RejectAction(val reason: String)
|
|
||||||
data class StoredProcedure(val input: Map<String, Any>, val output: Map<String, ResultType> = hashMapOf())
|
|
||||||
|
|
||||||
object Entities {
|
object Entities {
|
||||||
private val logger = LoggerFactory.getLogger("Entities")
|
private val logger = LoggerFactory.getLogger("Entities")
|
||||||
|
private val OK = mapOf("status" to true)
|
||||||
fun delete(ctx: Context) {
|
fun delete(ctx: Context) {
|
||||||
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
|
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
|
||||||
e.deletedBy = Session.currentUser()
|
e.deletedBy = Session.currentUser()
|
||||||
e.deletedOn = LocalDateTime.now()
|
e.deletedOn = LocalDateTime.now()
|
||||||
e.update()
|
e.update()
|
||||||
e.delete()
|
e.delete()
|
||||||
|
ctx.json(OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun patch(ctx: Context) {
|
fun patch(ctx: Context) {
|
||||||
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
|
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
|
||||||
val pv = ctx.bodyAsClass<Map<String, Any>>()
|
val pv = ctx.bodyAsClass<Map<String, Any>>()
|
||||||
|
verifyKeys(pv)
|
||||||
|
|
||||||
pv.forEach { (key, value) ->
|
pv.forEach { (key, value) ->
|
||||||
e.data[key] = value;
|
e.data[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.update()
|
e.update()
|
||||||
|
ctx.json(OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(ctx: Context) {
|
fun update(ctx: Context) {
|
||||||
@@ -117,121 +121,119 @@ object Entities {
|
|||||||
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
|
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
|
||||||
|
|
||||||
val newData = ctx.bodyAsClass<Map<String, Any>>()
|
val newData = ctx.bodyAsClass<Map<String, Any>>()
|
||||||
|
verifyKeys(newData)
|
||||||
if (purgeExisting) {
|
if (purgeExisting) {
|
||||||
e.data.clear();
|
e.data.clear();
|
||||||
}
|
}
|
||||||
e.data.putAll(newData)
|
e.data.putAll(newData)
|
||||||
|
|
||||||
e.update()
|
e.update()
|
||||||
|
ctx.json(OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun action(ctx: Context) {}
|
private fun verifyKeys(newData: Map<String, Any>) {
|
||||||
fun approve(ctx: Context) {
|
newData.keys.forEach { key ->
|
||||||
approveOrReject(ctx, ApprovalStatus.APPROVED)
|
if (!SafeStringDeserializer.isSafe(key)) throw IllegalArgumentException("$key is invalid from $newData ")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reject(ctx: Context) {
|
|
||||||
approveOrReject(ctx, ApprovalStatus.REJECTED)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun approveOrReject(ctx: Context, rejected: ApprovalStatus) {
|
fun search(ctx: Context) {
|
||||||
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
|
val sql = ctx.bodyAsClass<SearchParams>()
|
||||||
val reject = ctx.bodyAsClass<RejectAction>()
|
verifyKeys(sql.params)
|
||||||
e.approvalStatus = rejected
|
|
||||||
e.comments.add(Comments(text = reject.reason, by = currentUser()))
|
|
||||||
e.save()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun executeScript(ctx: Context) {
|
val entity = ctx.pathParam("entity").lowercase()
|
||||||
val name = ctx.pathParam("name")
|
val noCreatedFilter = currentRoles().contains("ROLE_ADMIN") || sql.createdBy.isNullOrEmpty()
|
||||||
val file = ctx.pathParam("file")
|
val createdFilter = if (noCreatedFilter) "" else "and created_by = :cBy"
|
||||||
val params = ctx.bodyAsClass<Map<String, Any>>()
|
val searchJsonMap = sql.params.map { e -> Pair(e.key, e.value.getValue()) }.toMap()
|
||||||
ctx.json(
|
val fl = database.find(DataModel::class.java)
|
||||||
Scripting.execute(file, name, params)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun executeStoredProcedure(ctx: Context) {
|
|
||||||
val name = ctx.pathParam("name")
|
|
||||||
val sp = ctx.bodyAsClass<StoredProcedure>()
|
|
||||||
|
|
||||||
val inputParams = sp.input.entries.toList()
|
|
||||||
val outputParams = sp.output.entries.toList()
|
|
||||||
|
|
||||||
val placeholders = (0..inputParams.size + 1).joinToString(",") { "?" }
|
|
||||||
|
|
||||||
val sql = "{call $name($placeholders)}"
|
|
||||||
val cs: CallableSql = database.createCallableSql(sql)
|
|
||||||
|
|
||||||
inputParams.forEachIndexed { index, entry ->
|
|
||||||
cs.setParameter(index + 1, entry.value)
|
|
||||||
}
|
|
||||||
cs.setParameter(inputParams.size + 1, Session.currentTenant())
|
|
||||||
|
|
||||||
outputParams.forEachIndexed { idx, entry ->
|
|
||||||
when (entry.value) {
|
|
||||||
ResultType.INTEGER -> cs.registerOut(idx + 1, Types.INTEGER)
|
|
||||||
ResultType.DECIMAL -> cs.registerOut(idx + 1, Types.DOUBLE)
|
|
||||||
ResultType.STRING -> cs.registerOut(idx + 1, Types.VARCHAR)
|
|
||||||
ResultType.DATETIME -> cs.registerOut(idx + 1, Types.DATE)
|
|
||||||
ResultType.ARRAY -> cs.registerOut(idx + 1, Types.ARRAY)
|
|
||||||
ResultType.OBJECT -> cs.registerOut(idx + 1, Types.JAVA_OBJECT)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
val done = database.execute(cs)
|
|
||||||
val output = outputParams.mapIndexed { index, entry ->
|
|
||||||
Pair(entry.key, cs.getObject(index + 1))
|
|
||||||
}.toMap()
|
|
||||||
|
|
||||||
ctx.json(
|
|
||||||
mapOf(
|
|
||||||
"done" to done,
|
|
||||||
"output" to output
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sqlQueryRaw(ctx: Context) {
|
|
||||||
val sql = ctx.bodyAsClass<RawQuery>()
|
|
||||||
logger.warn("running sql ${sql.sql}, with params ${sql.params}")
|
|
||||||
ctx.json(
|
|
||||||
database.find(DataModel::class.java)
|
|
||||||
.setRawSql(
|
.setRawSql(
|
||||||
RawSqlBuilder.parse(sql.sql).create()
|
RawSqlBuilder.parse(
|
||||||
).apply {
|
"""
|
||||||
sql.params.forEach { (t, u) ->
|
select sys_pk,
|
||||||
setParameter(t, u.getValue())
|
deleted_on,
|
||||||
}
|
current_approval_level,
|
||||||
}
|
required_approval_levels,
|
||||||
.findList()
|
deleted,
|
||||||
|
version,
|
||||||
|
created_at,
|
||||||
|
modified_at,
|
||||||
|
deleted_by,
|
||||||
|
approval_status,
|
||||||
|
tags,
|
||||||
|
comments,
|
||||||
|
tenant_id,
|
||||||
|
unique_identifier,
|
||||||
|
entity_name,
|
||||||
|
data,
|
||||||
|
created_by,
|
||||||
|
modified_by
|
||||||
|
from data_model
|
||||||
|
where entity_name = :e
|
||||||
|
and created_at between :from and :to
|
||||||
|
and data @> cast(:search as jsonb)
|
||||||
|
and deleted = false
|
||||||
|
$createdFilter
|
||||||
|
order by sysPk desc
|
||||||
|
""".trimIndent()
|
||||||
|
).create()
|
||||||
)
|
)
|
||||||
|
.setParameter("from", sql.dateRange.first())
|
||||||
}
|
.setParameter("to", sql.dateRange.last().plusDays(1))
|
||||||
|
.setParameter("e", entity)
|
||||||
fun sqlQueryById(ctx: Context) {
|
.setParameter("search", objectMapper.writeValueAsString(searchJsonMap))
|
||||||
val sql = ctx.bodyAsClass<QueryById>()
|
|
||||||
val sqlId = ctx.pathParam("id")
|
|
||||||
logger.warn("running sqlId $sqlId, with params ${sql.params}")
|
|
||||||
|
|
||||||
val entity = ctx.pathParam("entity")
|
|
||||||
val query = database.find(SqlModel::class.java)
|
|
||||||
.where()
|
|
||||||
.eq("entityName", entity)
|
|
||||||
.eq("sqlId", sqlId)
|
|
||||||
.findOne() ?: throw NotFoundResponse("sql not found for $entity, $sqlId")
|
|
||||||
|
|
||||||
ctx.json(
|
|
||||||
database.find(DataModel::class.java)
|
|
||||||
.setRawSql(RawSqlBuilder.parse(query.sql).create())
|
|
||||||
.apply {
|
.apply {
|
||||||
sql.params.forEachIndexed { index, entry ->
|
if (!noCreatedFilter) {
|
||||||
setParameter(index + 1, entry.getValue())
|
logger.warn("Set Created By Filter to ${currentUser()}")
|
||||||
|
setParameter("cBy", currentUser())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.findList()
|
.findList()
|
||||||
)
|
|
||||||
|
|
||||||
|
logger.warn("Search jsonMap [$searchJsonMap] => ${fl.size} entries")
|
||||||
|
|
||||||
|
ctx.json(fl)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val entity = ctx.pathParam("entity").uppercase()
|
||||||
|
val pageNo = ctx.queryParam("pageNo")?.toInt() ?: 1
|
||||||
|
val perPage = ctx.queryParam("perPage")?.toInt() ?: 100
|
||||||
|
val cnt = database.find(DataModel::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("entityName", entity.lowercase())
|
||||||
|
.setFirstRow((pageNo - 1) * perPage)
|
||||||
|
.setMaxRows(perPage)
|
||||||
|
.orderBy("sysPk desc")
|
||||||
|
.findPagedList()
|
||||||
|
|
||||||
|
ctx.json(cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNextSeqNo(ctx: Context) {
|
||||||
|
val entity = ctx.pathParam("entity").uppercase()
|
||||||
|
|
||||||
|
val prefix = "$entity/"
|
||||||
|
val plantId = ctx.queryParam("plantId") ?: throw BadRequestResponse("plantId not sent")
|
||||||
|
val plant = database.find(Plant::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("plantId", plantId)
|
||||||
|
.findOne() ?: throw BadRequestResponse("plant missing for $plantId")
|
||||||
|
|
||||||
|
val inventoryPrefix = plant.prefixes?.get(entity) ?: prefix
|
||||||
|
|
||||||
|
val cnt = (database.find(DataModel::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("entityName", entity.lowercase())
|
||||||
|
.eq("data->>'plantId'", plantId)
|
||||||
|
.findCount() + 1)
|
||||||
|
.toString()
|
||||||
|
.padStart(6, '0')
|
||||||
|
|
||||||
|
val seq = SequenceNumber(inventoryPrefix + cnt)
|
||||||
|
ctx.json(seq).status(HttpStatus.OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun view(it: Context) {
|
fun view(it: Context) {
|
||||||
@@ -266,6 +268,7 @@ object Entities {
|
|||||||
}
|
}
|
||||||
this.approvalStatus = ApprovalStatus.APPROVED
|
this.approvalStatus = ApprovalStatus.APPROVED
|
||||||
}
|
}
|
||||||
|
verifyKeys(dataModel.data)
|
||||||
|
|
||||||
database.save(
|
database.save(
|
||||||
dataModel.apply {
|
dataModel.apply {
|
||||||
@@ -326,18 +329,7 @@ object Entities {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!setupEntity.preSaveScript.isNullOrEmpty()) {
|
|
||||||
val ok = Scripting.execute(setupEntity.preSaveScript!!, "preSave", this) as Boolean
|
|
||||||
if (!ok) {
|
|
||||||
throw BadRequestResponse("PreSave Failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setupEntity.approvalLevels > 0) {
|
|
||||||
|
|
||||||
this.approvalStatus = ApprovalStatus.PENDING
|
|
||||||
this.requiredApprovalLevels = setupEntity.approvalLevels
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,12 +342,13 @@ object Entities {
|
|||||||
|
|
||||||
database.save(
|
database.save(
|
||||||
AuditLog().apply {
|
AuditLog().apply {
|
||||||
auditType = AuditType.CREATE
|
this.auditType = AuditType.CREATE
|
||||||
this.entity = entity
|
this.entity = entity
|
||||||
uniqueIdentifier = dataModel.uniqueIdentifier
|
this.uniqueIdentifier = dataModel.uniqueIdentifier
|
||||||
this.data = dataModel.data
|
this.data = dataModel.data
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ctx.json(OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isValidDate(f: String) = try {
|
private fun isValidDate(f: String) = try {
|
||||||
@@ -380,224 +373,11 @@ object Entities {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object PurchaseOrder {
|
data class SearchParams(
|
||||||
fun get(ctx :Context){
|
val params: Map<String, QueryParam> = mapOf(),
|
||||||
val id = ctx.pathParam("id")
|
val createdBy: String?,
|
||||||
val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
|
val dateRange: List<LocalDate> = listOf(LocalDate.now().minusDays(7), LocalDate.now())
|
||||||
|
|
||||||
ctx.json(po)
|
|
||||||
}
|
|
||||||
fun create(ctx :Context){
|
|
||||||
val po = ctx.bodyAsClass<PurchaseOrder>()
|
|
||||||
database.save(po)
|
|
||||||
ctx.result("po created")
|
|
||||||
}
|
|
||||||
fun approve(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
|
|
||||||
po.approvalStatus = ApprovalStatus.APPROVED
|
|
||||||
po.save()
|
|
||||||
ctx.result("po with id $id approved")
|
|
||||||
//reject all other pos pertaining to the same tx ??
|
|
||||||
}
|
|
||||||
fun reject(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val po = database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
|
|
||||||
po.approvalStatus = ApprovalStatus.REJECTED
|
|
||||||
po.save()
|
|
||||||
ctx.result("po with id $id rejected")
|
|
||||||
}
|
|
||||||
fun quoteReference(ctx :Context){
|
|
||||||
//gets the quote reference on which this po is based on
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val quote = database.find(Quotation::class.java)
|
|
||||||
.where()
|
|
||||||
.eq("referenceQuotation", id)
|
|
||||||
?: throw NotFoundResponse("reference quotation not found for po $id")
|
|
||||||
ctx.json(quote)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ProductSearch(
|
|
||||||
var isSort: String? = null
|
|
||||||
)
|
)
|
||||||
|
|
||||||
object ProductCtrl {
|
data class SequenceNumber(val number: String)
|
||||||
fun get(ctx :Context){
|
|
||||||
val hsnCode = ctx.pathParam("hsnCode")
|
|
||||||
val product = database.find(Product::class.java, hsnCode) ?: throw NotFoundResponse("Product not found for $hsnCode")
|
|
||||||
|
|
||||||
ctx.json(product)
|
|
||||||
}
|
|
||||||
fun getAll(ctx: Context){
|
|
||||||
val productList = Session.database.find(Product::class.java)
|
|
||||||
.findList()
|
|
||||||
//.sortedBy { it.hsnCode }
|
|
||||||
|
|
||||||
ctx.json(productList)
|
|
||||||
}
|
|
||||||
fun create(ctx :Context){
|
|
||||||
val product = ctx.bodyAsClass<Product>()
|
|
||||||
database.save(product)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun delete(ctx: Context) {
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val product = database.delete(Product::class.java, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun patch(ctx: Context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun update(ctx: Context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
fun prodExcel(it: Context) {
|
|
||||||
val product = database.find(Product::class.java).findList()
|
|
||||||
it.result(CreateExcel(product)).contentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
|
||||||
.header("Content-Disposition", "attachment; filename=\"product.xlsx\"")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object Quotation {
|
|
||||||
fun get(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val quote = database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for $id")
|
|
||||||
ctx.json(quote)
|
|
||||||
}
|
|
||||||
fun create(ctx :Context){
|
|
||||||
val quote = ctx.bodyAsClass<Quotation>()
|
|
||||||
//we have to check if the quotation created date is below the expiry of rfq
|
|
||||||
val rfq = database.find(com.restapi.domain.ReqForQuote::class.java)
|
|
||||||
.where()
|
|
||||||
.eq("reqForQuoteNum", quote.reqForQuoteNum)
|
|
||||||
.findOne()
|
|
||||||
if(rfq != null){
|
|
||||||
//compare dates
|
|
||||||
if(quote.quoteDate!! <= rfq.openTill) {
|
|
||||||
//valid
|
|
||||||
database.save(quote)
|
|
||||||
ctx.result("quote created")
|
|
||||||
}else {
|
|
||||||
ctx.result("request for quote closed")
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
throw NotFoundResponse("request for quote not found for this quotation")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fun delete(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val quote = database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for id $id")
|
|
||||||
quote.delete()
|
|
||||||
ctx.result("quote with $id deleted")
|
|
||||||
}
|
|
||||||
fun generatePO(ctx :Context){
|
|
||||||
//user should be redirected to a po form submission with prefilled values
|
|
||||||
//create a PO object with values from the quote and then send it as body to vendor/po/create ??
|
|
||||||
|
|
||||||
}
|
|
||||||
fun reqForQuote(ctx :Context){
|
|
||||||
val reqForQuoteNum = ctx.pathParam(("rfqNum"))
|
|
||||||
val rfq = database.find(RequestForQuote::class.java)
|
|
||||||
.where()
|
|
||||||
.eq("reqForQuoteNum", reqForQuoteNum)
|
|
||||||
?: throw NotFoundResponse("request for quote not found for this quotation")
|
|
||||||
ctx.json(rfq)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
object Document {
|
|
||||||
fun get(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val doc = database.find(Document::class.java, id) ?: throw NotFoundResponse("no doc found with id $id")
|
|
||||||
ctx.json(doc)
|
|
||||||
}
|
|
||||||
fun create(ctx :Context){
|
|
||||||
val doc = ctx.bodyAsClass<Document>()
|
|
||||||
database.save(doc)
|
|
||||||
ctx.result("doc created")
|
|
||||||
}
|
|
||||||
fun print(ctx :Context){
|
|
||||||
//would be handled in the frontend ??
|
|
||||||
}
|
|
||||||
fun delete(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val doc = database.find(Document::class.java, id) ?: throw NotFoundResponse("no doc found with id $id")
|
|
||||||
//doc.delete()
|
|
||||||
ctx.result("document deleted")
|
|
||||||
}
|
|
||||||
fun getWithRefId(ctx :Context){
|
|
||||||
//fetches a particular doc (po, quote) with ref id
|
|
||||||
val refId = ctx.pathParam("refId")
|
|
||||||
val doc = database.find(Document::class.java)
|
|
||||||
.where()
|
|
||||||
.eq("refId", refId)
|
|
||||||
?: throw NotFoundResponse("no doc found for refId $refId")
|
|
||||||
ctx.json(doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
object Vendor {
|
|
||||||
fun get(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val vendor = database.find(Vendor::class.java, id) ?: throw NotFoundResponse("no vendor found with id $id")
|
|
||||||
ctx.json(vendor)
|
|
||||||
}
|
|
||||||
fun create(ctx :Context){
|
|
||||||
val vendor = ctx.bodyAsClass<Vendor>()
|
|
||||||
database.save(vendor)
|
|
||||||
ctx.result("vendor created")
|
|
||||||
}
|
|
||||||
fun update(ctx :Context){
|
|
||||||
|
|
||||||
}
|
|
||||||
fun delete(ctx :Context){
|
|
||||||
|
|
||||||
}
|
|
||||||
fun getQuotes(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val quotes = database.find(Quotation::class.java)
|
|
||||||
.where()
|
|
||||||
.eq("vendor", id)
|
|
||||||
.findList()
|
|
||||||
ctx.json(quotes)
|
|
||||||
}
|
|
||||||
fun getPos(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val pos = database.find(PurchaseOrder::class.java)
|
|
||||||
.where()
|
|
||||||
.eq("vendor", id)
|
|
||||||
.findList()
|
|
||||||
ctx.json(pos)
|
|
||||||
}
|
|
||||||
fun rate(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val rating = ctx.pathParam("rating").toDouble()
|
|
||||||
val vendor = database.find(Vendor::class.java, id) ?: throw NotFoundResponse("vendor not found for id $id")
|
|
||||||
//could place some rating validation checks
|
|
||||||
vendor.rating = rating
|
|
||||||
vendor.save()
|
|
||||||
ctx.result("rating changed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
object RequestForQuote {
|
|
||||||
fun create(ctx :Context) {
|
|
||||||
val rfq = ctx.bodyAsClass<ReqForQuote>()
|
|
||||||
database.save(rfq)
|
|
||||||
//ctx.result("request for quote created")
|
|
||||||
//ctx.json(rfq)
|
|
||||||
//ctx.status(HttpStatus.CREATED)
|
|
||||||
//ctx.json("asss")
|
|
||||||
}
|
|
||||||
fun get(ctx :Context){
|
|
||||||
val id = ctx.pathParam("id")
|
|
||||||
val rfq = database.find(ReqForQuote::class.java, id) ?: throw NotFoundResponse("request for quote not found for id $id")
|
|
||||||
ctx.json(rfq)
|
|
||||||
}
|
|
||||||
fun update(ctx :Context){
|
|
||||||
//shuld we compare the new body fields with preexisting ones and prepare a sql query to update those fields??
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,184 +1,727 @@
|
|||||||
package com.restapi.controllers
|
package com.restapi.controllers
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.restapi.domain.*
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
import com.restapi.domain.Session.currentUserPlants
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
|
||||||
import com.restapi.domain.Product
|
|
||||||
import com.restapi.domain.Session
|
|
||||||
import com.restapi.domain.Session.database
|
import com.restapi.domain.Session.database
|
||||||
import com.restapi.domain.UOM
|
import org.apache.poi.hssf.usermodel.DVConstraint
|
||||||
import io.ebean.text.json.JsonContext
|
import org.apache.poi.hssf.usermodel.HSSFDataValidation
|
||||||
import io.javalin.http.Context
|
import org.apache.poi.hssf.usermodel.HSSFSheet
|
||||||
import org.apache.poi.ss.usermodel.Cell
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook
|
||||||
import org.apache.poi.ss.usermodel.CellType
|
import org.apache.poi.ss.usermodel.*
|
||||||
import org.apache.poi.ss.usermodel.Row
|
import org.apache.poi.ss.util.CellRangeAddressList
|
||||||
import org.apache.poi.ss.usermodel.WorkbookFactory
|
import java.io.File
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
import java.io.FileOutputStream
|
||||||
import java.io.ByteArrayInputStream
|
import java.text.SimpleDateFormat
|
||||||
import java.io.ByteArrayOutputStream
|
import java.time.LocalDate
|
||||||
import java.io.FileInputStream
|
import java.time.ZoneId
|
||||||
import java.io.InputStream
|
import java.util.*
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
fun CreateExcel(productList: List<Product>): InputStream {
|
fun createHeaderRow(cols: List<String>, sh: HSSFSheet, wb: Workbook) {
|
||||||
val wb = XSSFWorkbook()
|
val boldFont = wb.createFont()
|
||||||
|
boldFont.bold = true
|
||||||
|
val style = wb.createCellStyle()
|
||||||
|
style.setFont(boldFont)
|
||||||
|
style.locked = true
|
||||||
|
|
||||||
|
sh.createRow(0).apply {
|
||||||
|
cols.forEachIndexed { index, value ->
|
||||||
|
val cell = createCell(index)
|
||||||
|
cell.setCellValue(value)
|
||||||
|
cell.setCellStyle(style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.parseDate(format: String): Date? {
|
||||||
|
val locale = Locale.getDefault()
|
||||||
|
return try {
|
||||||
|
SimpleDateFormat(format, locale).parse(this)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dateFromCellHelper(cell: Cell): LocalDate? {
|
||||||
|
val date = when (cell.cellType) {
|
||||||
|
CellType.STRING -> cell.stringCellValue.parseDate("yyyy-MM-dd")
|
||||||
|
CellType.NUMERIC -> {
|
||||||
|
if (DateUtil.isCellDateFormatted(cell)) {
|
||||||
|
cell.getDateCellValue()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
return date?.toInstant()?.atZone(ZoneId.systemDefault())?.toLocalDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stringFromCellHelper(cell: Cell): String {
|
||||||
|
val string = when (cell.cellType) {
|
||||||
|
CellType.NUMERIC -> cell.numericCellValue.toString()
|
||||||
|
CellType.STRING -> cell.stringCellValue
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doubleFromCellHelper(cell: Cell): Double {
|
||||||
|
val double = when (cell.cellType) {
|
||||||
|
CellType.NUMERIC -> cell.numericCellValue
|
||||||
|
CellType.STRING -> cell.stringCellValue.toDoubleOrNull()
|
||||||
|
else -> 0.0
|
||||||
|
}
|
||||||
|
return double ?: 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun longIntFromCellHelper(cell: Cell): Long {
|
||||||
|
val long = when (cell.cellType) {
|
||||||
|
CellType.NUMERIC -> cell.numericCellValue.toLong()
|
||||||
|
CellType.STRING -> cell.stringCellValue.toLong()
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
return long
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class FileType {
|
||||||
|
QUOTES, POS, VENDORS, PRODS, DOCS
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class EnumFor {
|
||||||
|
UOM, DocType
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveExcelFileLocally(fileName: String, wb: Workbook) {
|
||||||
|
val path = "./excel"
|
||||||
|
val file = File(path, fileName)
|
||||||
|
|
||||||
|
if (!file.parentFile.exists()) {
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
}
|
||||||
|
val out = FileOutputStream(file)
|
||||||
|
wb.use {
|
||||||
|
it.write(out)
|
||||||
|
}
|
||||||
|
out.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TemplateExcelFile(fileType: FileType) {
|
||||||
|
when (fileType) {
|
||||||
|
FileType.QUOTES -> {
|
||||||
|
val headers: List<String> = listOf(
|
||||||
|
"Quotation Number",
|
||||||
|
"Date",
|
||||||
|
"Open Till",
|
||||||
|
"Product Id",
|
||||||
|
"Product Name",
|
||||||
|
"Product Unit Price",
|
||||||
|
"Quantity",
|
||||||
|
"Vendor Name",
|
||||||
|
"Vendor Address",
|
||||||
|
"RFQ Number",
|
||||||
|
"Total Amount",
|
||||||
|
"Terms and Conditions"
|
||||||
|
)
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
val sh = wb.createSheet()
|
val sh = wb.createSheet()
|
||||||
val rows: Row = sh.createRow(0)
|
createHeaderRow(headers, sh, wb)
|
||||||
rows.createCell(0).setCellValue("Name")
|
saveExcelFileLocally("Quotes_Template.xls", wb)
|
||||||
rows.createCell(1).setCellValue("Description")
|
|
||||||
rows.createCell(2).setCellValue("HSN")
|
|
||||||
rows.createCell(3).setCellValue("UOM")
|
|
||||||
|
|
||||||
var rowNum = 1
|
|
||||||
for (product in productList) {
|
|
||||||
val row: Row = sh.createRow(rowNum++)
|
|
||||||
|
|
||||||
row.createCell(0).setCellValue(product.name)
|
|
||||||
row.createCell(1).setCellValue(product.description)
|
|
||||||
row.createCell(2).setCellValue(product.hsnCode)
|
|
||||||
|
|
||||||
val uomCell: Cell = row.createCell(3)
|
|
||||||
uomCell.setCellValue(product.uom?.name ?: "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val baos = ByteArrayOutputStream()
|
FileType.POS -> {
|
||||||
wb.write(baos)
|
val headers: List<String> = listOf(
|
||||||
wb.close()
|
"Number",
|
||||||
|
"Date",
|
||||||
|
"Open Till",
|
||||||
|
"Reference Quotation Number",
|
||||||
|
"Vendor Name",
|
||||||
|
"Vendor Address",
|
||||||
|
"Product Id",
|
||||||
|
"Product Name",
|
||||||
|
"Unit Price",
|
||||||
|
"Quantity",
|
||||||
|
"Total Amount",
|
||||||
|
"Terms and Conditions"
|
||||||
|
)
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
saveExcelFileLocally("Purchase_Order_Template.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
return ByteArrayInputStream(baos.toByteArray())
|
FileType.VENDORS -> {
|
||||||
|
val headers: List<String> = listOf(
|
||||||
|
"Name", "MSME", "GST Number", "Address", "Rating", "Contact Name", "Contact Email", "Contact Mobile"
|
||||||
|
)
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
saveExcelFileLocally("Vendors_Template.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
FileType.PRODS -> {
|
||||||
|
val headers: List<String> = listOf("Id", "Name", "Description", "HSN Code", "UOM")
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
val r0 = CellRangeAddressList(0, 1000, 4, 4)
|
||||||
|
val dv0 = HSSFDataValidation(
|
||||||
|
r0, DVConstraint.createExplicitListConstraint(arrayOf("LTR", "MTR", "NOS", "ALL"))
|
||||||
|
).apply {
|
||||||
|
suppressDropDownArrow = true
|
||||||
|
}
|
||||||
|
sh.addValidationData(dv0)
|
||||||
|
saveExcelFileLocally("Products_Template.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
FileType.DOCS -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class validateExcel(
|
fun exportQuotations(quotes: List<Quotation>) {
|
||||||
val name: String,
|
val wb = HSSFWorkbook()
|
||||||
val description: String,
|
val sh = wb.createSheet()
|
||||||
val hsnCode: String,
|
|
||||||
val ok: Boolean,
|
|
||||||
val err: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
val app_common_om = jacksonObjectMapper().apply {
|
val headers: List<String> = listOf(
|
||||||
registerModule(JavaTimeModule())
|
"Quotation Number",
|
||||||
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
"Date",
|
||||||
|
"Open Till",
|
||||||
|
"Product Id",
|
||||||
|
"Product Name",
|
||||||
|
"Product Unit Price",
|
||||||
|
"Quantity",
|
||||||
|
"Vendor Name",
|
||||||
|
"Vendor Address",
|
||||||
|
"RFQ Number",
|
||||||
|
"Total AMount",
|
||||||
|
"Terms and Conditions"
|
||||||
|
)
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
var rowCnt = 1
|
||||||
|
for (quote in quotes) {
|
||||||
|
val prodCnt = quote.products.size
|
||||||
|
|
||||||
|
for (j in 0..<prodCnt) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0;
|
||||||
|
row.createCell(i++).setCellValue(quote.quoteNum)
|
||||||
|
row.createCell(i++).setCellValue(quote.quoteDate)
|
||||||
|
row.createCell(i++).setCellValue(quote.validTill)
|
||||||
|
//6 would be repeated
|
||||||
|
row.createCell(i++).setCellValue(quote.products[j].productId.toString())
|
||||||
|
row.createCell(i++).setCellValue(quote.products[j].productName)
|
||||||
|
row.createCell(i++).setCellValue(quote.products[j].unitPrice)
|
||||||
|
row.createCell(i++).setCellValue(quote.products[j].quantity)
|
||||||
|
|
||||||
|
row.createCell(i++).setCellValue(quote.vendor?.name)
|
||||||
|
row.createCell(i++).setCellValue(quote.vendor?.address)
|
||||||
|
|
||||||
|
row.createCell(i++).setCellValue(quote.reqForQuoteNum)
|
||||||
|
row.createCell(i++).setCellValue(quote.totalAmount)
|
||||||
|
|
||||||
|
row.createCell(i++).setCellValue(quote.tnc?.joinToString(";"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("Quotes.xls", wb)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ExcelRead(): String{
|
fun exportVendors(vendors: List<Vendor>) {
|
||||||
val inputStream = FileInputStream("C:\\Users\\vinay\\IdeaProjects\\readymixerp_modules_api_git\\product-4.xlsx")
|
val wb = HSSFWorkbook()
|
||||||
val workbook = WorkbookFactory.create(inputStream)
|
val sh = wb.createSheet()
|
||||||
val workSheet = workbook.getSheetAt(0)
|
|
||||||
var h = true
|
|
||||||
//Header check
|
|
||||||
if(workSheet.getRow(0).getCell(0).stringCellValue.equals("Name")) {
|
|
||||||
if (workSheet.getRow(0).getCell(1).stringCellValue.equals("Description")) {
|
|
||||||
if (workSheet.getRow(0).getCell(2).stringCellValue.equals("HSN")) {
|
|
||||||
if (workSheet.getRow(0).getCell(3).stringCellValue.equals("UOM")) {
|
|
||||||
h = false
|
|
||||||
}else return "Header UOM mismatch"
|
|
||||||
}else return "Header-HSN mismatch"
|
|
||||||
}else return "Header-Desc mismatch"
|
|
||||||
}else return "Header-Name mismatch"
|
|
||||||
|
|
||||||
val resp = arrayListOf<validateExcel>()
|
val headers: List<String> = listOf(
|
||||||
|
"No.", "Name", "MSME", "GST Number", "Address", "Rating", "Contact Name", "Contact Email", "Contact Mobile"
|
||||||
|
)
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
if(h==false) {
|
val totalCols = headers.size
|
||||||
workSheet.rowIterator().forEach { row ->
|
var rowCnt = 1
|
||||||
|
|
||||||
|
for (vendor in vendors) {
|
||||||
|
val contactCnt = vendor.contacts.size
|
||||||
|
for (j in 0..<contactCnt) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue((rowCnt - 1).toString())
|
||||||
|
row.createCell(i++).setCellValue(vendor.name)
|
||||||
|
row.createCell(i++).setCellValue(vendor.msme)
|
||||||
|
row.createCell(i++).setCellValue(vendor.gstNumber)
|
||||||
|
row.createCell(i++).setCellValue(vendor.address)
|
||||||
|
row.createCell(i++).setCellValue(vendor.rating)
|
||||||
|
row.createCell(i++).setCellValue(vendor.contacts[j].name)
|
||||||
|
row.createCell(i++).setCellValue(vendor.contacts[j].email)
|
||||||
|
row.createCell(i++).setCellValue(vendor.contacts[j].mobile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("VendorList.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportProds(prods: List<Product>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf("Id", "Name", "Description", "HSN Code", "UOM")
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
|
||||||
|
for (prod in prods) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(prod.code.toString())
|
||||||
|
row.createCell(i++).setCellValue(prod.name)
|
||||||
|
row.createCell(i++).setCellValue(prod.description)
|
||||||
|
row.createCell(i++).setCellValue(prod.hsnCode)
|
||||||
|
row.createCell(i++).setCellValue(prod.uom?.name)
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("Products.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportPos(pos: List<PurchaseOrder>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf(
|
||||||
|
"Number",
|
||||||
|
"Date",
|
||||||
|
"Open Till",
|
||||||
|
"Reference Quotation Number",
|
||||||
|
"Vendor Name",
|
||||||
|
"Vendor Address",
|
||||||
|
"Product Id",
|
||||||
|
"Product Name",
|
||||||
|
"Unit Price",
|
||||||
|
"Quantity",
|
||||||
|
"Loading Site",
|
||||||
|
"Unloading Plant",
|
||||||
|
"Total Amount",
|
||||||
|
"Terms and Conditions"
|
||||||
|
)
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
val vmap = ConcurrentHashMap<Long, Vendor>()
|
||||||
|
val plants = currentUserPlants()
|
||||||
|
for (po in pos) {
|
||||||
|
val prodCnt = po.products.size
|
||||||
|
|
||||||
|
for (j in 0..<prodCnt) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(po.poNum)
|
||||||
|
row.createCell(i++).setCellValue(po.poDate)
|
||||||
|
row.createCell(i++).setCellValue(po.validTill)
|
||||||
|
row.createCell(i++).setCellValue(po.referenceQuotation)
|
||||||
|
val vendorId = po.vendor!!.sysPk
|
||||||
|
val vendor = vmap.computeIfAbsent(vendorId) {
|
||||||
|
database.find(Vendor::class.java, vendorId)!!
|
||||||
|
}
|
||||||
|
row.createCell(i++).setCellValue(vendor.name)
|
||||||
|
|
||||||
|
//6 would be repeated
|
||||||
|
row.createCell(i++).setCellValue(po.products[j].productId.toString())
|
||||||
|
row.createCell(i++).setCellValue(po.products[j].productName)
|
||||||
|
row.createCell(i++).setCellValue(po.products[j].unitPrice)
|
||||||
|
row.createCell(i++).setCellValue(po.products[j].quantity)
|
||||||
|
|
||||||
|
if (po.allLoadingSite) {
|
||||||
|
|
||||||
|
row.createCell(i++).setCellValue("All Site")
|
||||||
|
} else {
|
||||||
|
row.createCell(i++).setCellValue(po.loadingSiteId?.toString())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (po.allUnloadingSite) {
|
||||||
|
row.createCell(i++).setCellValue("All Plants")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
row.createCell(i++)
|
||||||
|
.setCellValue(po.unloadingPlantId)
|
||||||
|
}
|
||||||
|
|
||||||
|
row.createCell(i++).setCellValue(po.totalAmount)
|
||||||
|
row.createCell(i).setCellValue(po.tnc?.joinToString(";"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("Pos.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportIncomingInventory(tickets: List<IncomingInventory>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf(
|
||||||
|
"MRN",
|
||||||
|
"Date",
|
||||||
|
"Vendor Name",
|
||||||
|
"Vendor Bill Number",
|
||||||
|
"Vendor Bill Amount",
|
||||||
|
"Vehicle No",
|
||||||
|
"Loading Site",
|
||||||
|
"Unloading Site",
|
||||||
|
"Product Name",
|
||||||
|
"Unit Price",
|
||||||
|
"Quantity",
|
||||||
|
)
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
for (ticket in tickets) {
|
||||||
|
val prodCnt = ticket.products?.size
|
||||||
|
|
||||||
|
for (j in 0..<prodCnt!!) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(ticket.mrn)
|
||||||
|
row.createCell(i++).setCellValue(ticket.date)
|
||||||
|
row.createCell(i++).setCellValue(ticket.vendor?.name)
|
||||||
|
row.createCell(i++).setCellValue(ticket.vendorBillNum)
|
||||||
|
row.createCell(i++).setCellValue(ticket.vendorBillAmount)
|
||||||
|
row.createCell(i++).setCellValue(ticket.vehicle)
|
||||||
|
row.createCell(i++).setCellValue(ticket.loading)
|
||||||
|
row.createCell(i++).setCellValue(ticket.unloading)
|
||||||
|
|
||||||
|
//6 would be repeated
|
||||||
|
row.createCell(i++).setCellValue(ticket.products!![j].productName)
|
||||||
|
row.createCell(i++).setCellValue(ticket.products!![j].unitPrice)
|
||||||
|
row.createCell(i++).setCellValue(ticket.products!![j].quantity)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("IncomingInventory.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportOutgoingInventory(tickets: List<OutgoingInventory>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf(
|
||||||
|
"MDN",
|
||||||
|
"Date",
|
||||||
|
"Out Mode",
|
||||||
|
"Purpose",
|
||||||
|
"Product Id",
|
||||||
|
"Product Name",
|
||||||
|
"Unit Price",
|
||||||
|
"Quantity",
|
||||||
|
)
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
for (ticket in tickets) {
|
||||||
|
val prodCnt = ticket.products?.size
|
||||||
|
|
||||||
|
for (j in 0..<prodCnt!!) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(ticket.mdn)
|
||||||
|
row.createCell(i++).setCellValue(ticket.date)
|
||||||
|
row.createCell(i++).setCellValue(ticket.outMode.toString())
|
||||||
|
row.createCell(i++).setCellValue(ticket.purpose)
|
||||||
|
|
||||||
|
//6 would be repeated
|
||||||
|
row.createCell(i++).setCellValue(ticket.products!![j].productId.toString())
|
||||||
|
row.createCell(i++).setCellValue(ticket.products!![j].productName)
|
||||||
|
row.createCell(i++).setCellValue(ticket.products!![j].unitPrice)
|
||||||
|
row.createCell(i++).setCellValue(ticket.products!![j].quantity)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("OutgoingInventory.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportPayments(payments: List<Payment>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf("Reference Number", "Vendor", "Amount Paid", "Amount Deducted", "Excess Amount")
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
|
||||||
|
for (pmt in payments) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(pmt.refNumber)
|
||||||
|
row.createCell(i++).setCellValue(pmt.vendor?.name)
|
||||||
|
row.createCell(i++).setCellValue(pmt.amount)
|
||||||
|
pmt.amountDeducted?.let { row.createCell(i++).setCellValue(it) }
|
||||||
|
pmt.excessAmount?.let { row.createCell(i++).setCellValue(it) }
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("Payments.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportInvoices(invoices: List<Invoice>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf(
|
||||||
|
"Number",
|
||||||
|
"Date",
|
||||||
|
"Reference PO",
|
||||||
|
"Status",
|
||||||
|
"Vendor Name",
|
||||||
|
"Vendor Address",
|
||||||
|
"Product Id",
|
||||||
|
"Product Name",
|
||||||
|
"Unit Price",
|
||||||
|
"Quantity",
|
||||||
|
"Total Amount"
|
||||||
|
)
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
for (invoice in invoices) {
|
||||||
|
val prodCnt = invoice.products?.size
|
||||||
|
|
||||||
|
for (j in 0..<prodCnt!!) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(invoice.number)
|
||||||
|
row.createCell(i++).setCellValue(invoice.date)
|
||||||
|
row.createCell(i++).setCellValue(invoice.poNum)
|
||||||
|
row.createCell(i++).setCellValue(invoice.status.toString())
|
||||||
|
row.createCell(i++).setCellValue(invoice.vendor?.name)
|
||||||
|
row.createCell(i++).setCellValue(invoice.vendor?.address)
|
||||||
|
|
||||||
|
//6 would be repeated
|
||||||
|
row.createCell(i++).setCellValue(invoice.products?.get(j)?.productId?.toString() ?: "NA")
|
||||||
|
row.createCell(i++).setCellValue(invoice.products?.get(j)?.productName ?: "NA")
|
||||||
|
invoice.products?.get(j)?.let { row.createCell(i++).setCellValue(it.unitPrice) }
|
||||||
|
invoice.products?.get(j)?.let { row.createCell(i++).setCellValue(it.quantity) }
|
||||||
|
|
||||||
|
row.createCell(i++).setCellValue(invoice.totalAmount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("Invoices.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportFleets(fleets: List<Fleet>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf("Type", "Reg. Number", "Reg. Date", "Model", "Make", "Driver", "Mileage")
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
|
||||||
|
for (flt in fleets) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(flt.type)
|
||||||
|
row.createCell(i++).setCellValue(flt.regNumber)
|
||||||
|
row.createCell(i++).setCellValue(flt.regDate)
|
||||||
|
row.createCell(i++).setCellValue(flt.model)
|
||||||
|
row.createCell(i++).setCellValue(flt.make)
|
||||||
|
row.createCell(i++).setCellValue(flt.driver)
|
||||||
|
row.createCell(i++).setCellValue(flt.mileage)
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("Fleets.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportReminderLogs(logs: List<ReminderLog>) {
|
||||||
|
val wb = HSSFWorkbook()
|
||||||
|
val sh = wb.createSheet()
|
||||||
|
|
||||||
|
val headers: List<String> = listOf("Type", "Amount", "Frequency", "Reminder Date", "Acted Upon", "Vehicle")
|
||||||
|
createHeaderRow(headers, sh, wb)
|
||||||
|
|
||||||
|
var rowCnt = 1
|
||||||
|
|
||||||
|
for (log in logs) {
|
||||||
|
val row = sh.createRow(rowCnt++)
|
||||||
|
var i = 0
|
||||||
|
row.createCell(i++).setCellValue(log.reminderType)
|
||||||
|
row.createCell(i++).setCellValue(log.amount)
|
||||||
|
row.createCell(i++).setCellValue(log.reminder?.frequency.toString())
|
||||||
|
row.createCell(i++).setCellValue(log.reminderDate)
|
||||||
|
row.createCell(i++).setCellValue(log.actedUpon)
|
||||||
|
row.createCell(i++).setCellValue(log.reminder?.fleet?.regNumber)
|
||||||
|
}
|
||||||
|
saveExcelFileLocally("ReminderLogs.xls", wb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
//ImportFromExcel(FileType.QUOTES, "C:\\Users\\arsalan\\Downloads\\Book.xlsx")
|
||||||
|
TemplateExcelFile(FileType.PRODS)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImportFromExcel(fileType: FileType, filePath: String) {
|
||||||
|
val wb = WorkbookFactory.create(File(filePath))
|
||||||
|
val sh = wb.getSheetAt(0)
|
||||||
|
|
||||||
|
when (fileType) {
|
||||||
|
FileType.QUOTES -> {
|
||||||
|
//Quote Number, ProductName, Product Quantity, Total Amount, RFQ Number, Quote Date, Valid Till, TNC[], Documents[]
|
||||||
|
val quotesMap: MutableMap<String, Quotation> = mutableMapOf()
|
||||||
|
val quotesList: List<Quotation> = mutableListOf()
|
||||||
|
sh.rowIterator().forEach { row ->
|
||||||
|
if (row == null) {
|
||||||
|
//reached eof
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
val quoteNumber = stringFromCellHelper(row.getCell(0))
|
||||||
|
val quoteDt = dateFromCellHelper(row.getCell(1))
|
||||||
|
val rfqNum = stringFromCellHelper(row.getCell(2))
|
||||||
|
val quoteValidTill = dateFromCellHelper(row.getCell(3))
|
||||||
|
val vendorName = stringFromCellHelper(row.getCell(4))
|
||||||
|
val vendorGstNum = stringFromCellHelper(row.getCell(5))
|
||||||
|
val vendorAddress = stringFromCellHelper(row.getCell(6))
|
||||||
|
val prodName = stringFromCellHelper(row.getCell(7))
|
||||||
|
val prodQuantity = doubleFromCellHelper(row.getCell(8))
|
||||||
|
val prodUnitPrice = doubleFromCellHelper(row.getCell(9))
|
||||||
|
val totalQuoteAmount = doubleFromCellHelper(row.getCell(10))
|
||||||
|
val prod = POProducts(0, prodName, prodUnitPrice, prodQuantity)
|
||||||
|
|
||||||
|
if (quotesMap.containsKey(quoteNumber)) {
|
||||||
|
//duplicated row
|
||||||
|
quotesMap.get(quoteNumber)?.products?.add(prod)
|
||||||
|
} else {
|
||||||
|
val v = Vendor()
|
||||||
|
v.apply {
|
||||||
|
name = vendorName
|
||||||
|
address = vendorAddress
|
||||||
|
gstNumber = vendorGstNum
|
||||||
|
}
|
||||||
|
val quote = Quotation()
|
||||||
|
quote.apply {
|
||||||
|
quoteNum = quoteNumber
|
||||||
|
quoteDate = quoteDt
|
||||||
|
reqForQuoteNum = rfqNum
|
||||||
|
validTill = quoteValidTill
|
||||||
|
products = mutableListOf(prod)
|
||||||
|
vendor = v
|
||||||
|
totalAmount = totalQuoteAmount
|
||||||
|
}
|
||||||
|
quotesMap.put(quoteNumber, quote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//docs, tncs
|
||||||
|
// println("$quotesMap")
|
||||||
|
|
||||||
|
// quotesMap.forEach { (k, v) ->
|
||||||
|
// println("$v")
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
FileType.POS -> {
|
||||||
|
//poNum, poDate, validTill, refQuoteNum, prodName, prodQuantity, totalAmount, products, vendorName, vendorGst, vendorAddress, tnc[]. docs[]
|
||||||
|
val poMap: MutableMap<String, PurchaseOrder> = mutableMapOf()
|
||||||
|
sh.rowIterator().forEach { row ->
|
||||||
if (row == null) return@forEach
|
if (row == null) return@forEach
|
||||||
|
val poNum = stringFromCellHelper(row.getCell(0))
|
||||||
|
val poDate = dateFromCellHelper(row.getCell(1))
|
||||||
|
val refQuoteNum = stringFromCellHelper(row.getCell(2))
|
||||||
|
val poValidTill = dateFromCellHelper(row.getCell(3))
|
||||||
|
val prodName = stringFromCellHelper(row.getCell(4))
|
||||||
|
val prodQuantity = doubleFromCellHelper(row.getCell(5))
|
||||||
|
val vendorName = stringFromCellHelper(row.getCell(6))
|
||||||
|
val vendorGstNum = stringFromCellHelper(row.getCell(7))
|
||||||
|
val vendorAddress = stringFromCellHelper(row.getCell(8))
|
||||||
|
val totalPoAmount = doubleFromCellHelper(row.getCell(9))
|
||||||
|
//tncs, docs
|
||||||
|
|
||||||
if (h) {
|
val prod = POProducts(
|
||||||
|
productId = 0,
|
||||||
val pName = row.getCell(0).run {
|
productName = prodName,
|
||||||
when {
|
unitPrice = 0.0,
|
||||||
this == null -> ""
|
quantity = prodQuantity,
|
||||||
this.cellType == CellType.STRING -> this.stringCellValue
|
billQty = prodQuantity,
|
||||||
else -> ""
|
gstPct = 0.0,
|
||||||
}
|
taxableValue = 0.0,
|
||||||
}
|
totalValue = 0.0,
|
||||||
|
description = "",
|
||||||
val pDesc = row.getCell(1).run {
|
uom = ""
|
||||||
when {
|
|
||||||
this == null -> ""
|
|
||||||
this.cellType == CellType.STRING -> this.stringCellValue
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val pHsn = row.getCell(2).run {
|
|
||||||
when {
|
|
||||||
this == null -> ""
|
|
||||||
this.cellType == CellType.STRING -> this.stringCellValue
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pName.isEmpty() && pDesc.isEmpty() && pHsn.isEmpty()) {
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
if (pName.isEmpty()) {
|
|
||||||
resp.add(
|
|
||||||
validateExcel(
|
|
||||||
name = pName,
|
|
||||||
description = pDesc,
|
|
||||||
hsnCode = pHsn,
|
|
||||||
ok = false,
|
|
||||||
err = "Product name is required"
|
|
||||||
)
|
)
|
||||||
)
|
if (poMap.containsKey(poNum)) {
|
||||||
return@forEach
|
//repeated row
|
||||||
}
|
poMap.get(poNum)?.products?.add(prod)
|
||||||
if (pDesc.isEmpty()) {
|
} else {
|
||||||
resp.add(
|
val vendor = Vendor()
|
||||||
validateExcel(
|
vendor.name = vendorName
|
||||||
name = pName,
|
vendor.address = vendorAddress
|
||||||
description = pDesc,
|
vendor.gstNumber = vendorGstNum
|
||||||
hsnCode = pHsn,
|
val po = PurchaseOrder()
|
||||||
ok = false,
|
po.poNum = poNum
|
||||||
err = "Product description is required"
|
po.poDate = poDate
|
||||||
)
|
po.referenceQuotation = refQuoteNum
|
||||||
)
|
po.validTill = poValidTill
|
||||||
return@forEach
|
poMap[poNum] = po
|
||||||
}
|
|
||||||
if (pHsn.isEmpty()) {
|
|
||||||
resp.add(
|
|
||||||
validateExcel(
|
|
||||||
name = pName,
|
|
||||||
description = pDesc,
|
|
||||||
hsnCode = pHsn,
|
|
||||||
ok = false,
|
|
||||||
err = "Product HSN is required"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return@forEach
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h = true
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return app_common_om.writeValueAsString(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun excelToDb(): List<Product> {
|
FileType.VENDORS -> {
|
||||||
val inputStream = FileInputStream("C:\\Users\\vinay\\IdeaProjects\\readymixerp_modules_api_git\\product-4.xlsx")
|
sh.rowIterator().forEach { row ->
|
||||||
val workbook = WorkbookFactory.create(inputStream)
|
//name, msme, gstNum, addresss, rating, contacts
|
||||||
val workSheet = workbook.getSheetAt(0)
|
if (row == null) return@forEach
|
||||||
|
val name = stringFromCellHelper(row.getCell(0))
|
||||||
|
val msme = stringFromCellHelper(row.getCell(1))
|
||||||
|
val gstNum = stringFromCellHelper(row.getCell(2))
|
||||||
|
val address = stringFromCellHelper(row.getCell(3))
|
||||||
|
val rating = doubleFromCellHelper(row.getCell(4))
|
||||||
|
|
||||||
for (row in workSheet) {
|
//vendor object
|
||||||
val cell1Value = row.getCell(0).stringCellValue
|
val vendor = Vendor()
|
||||||
val cell2Value = row.getCell(1).stringCellValue
|
vendor.name = name
|
||||||
val cell3Value = row.getCell(2).stringCellValue
|
vendor.address = address
|
||||||
val cell4Value = row.getCell(3).stringCellValue
|
vendor.msme = msme
|
||||||
|
vendor.gstNumber = gstNum
|
||||||
|
vendor.rating = rating
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileType.PRODS -> {
|
||||||
|
sh.rowIterator().forEach { row ->
|
||||||
|
if (row == null) return@forEach
|
||||||
|
//id, name, description, hsnCode, uom
|
||||||
|
val prodId = stringFromCellHelper(row.getCell(0))
|
||||||
|
val prodName = stringFromCellHelper(row.getCell(1))
|
||||||
|
val prodDesc = stringFromCellHelper(row.getCell(2))
|
||||||
|
val prodHsnCode = stringFromCellHelper(row.getCell(3))
|
||||||
|
val prodUom = stringFromCellHelper(row.getCell(4))
|
||||||
|
|
||||||
|
//new prod object
|
||||||
val prod = Product()
|
val prod = Product()
|
||||||
prod.name = cell1Value
|
prod.code = prodId
|
||||||
prod.description = cell2Value
|
prod.name = prodName
|
||||||
prod.hsnCode = cell3Value
|
prod.description = prodDesc
|
||||||
prod.uom = when(cell4Value) {
|
prod.hsnCode = prodHsnCode
|
||||||
|
prod.uom = when (prodUom) {
|
||||||
"nos" -> UOM.NOS
|
"nos" -> UOM.NOS
|
||||||
"ltr" -> UOM.LTR
|
"ltr" -> UOM.LTR
|
||||||
"mtr" -> UOM.MTR
|
"mtr" -> UOM.MTR
|
||||||
else -> UOM.ALL
|
else -> UOM.ALL
|
||||||
}
|
}
|
||||||
database.saveAll(prod)
|
|
||||||
}
|
}
|
||||||
val productList = Session.database.find(Product::class.java).findList()
|
}
|
||||||
return productList
|
|
||||||
}
|
|
||||||
|
|
||||||
|
FileType.DOCS -> {
|
||||||
|
sh.rowIterator().forEach { row ->
|
||||||
|
//Document Name, Document Type, RefID, url
|
||||||
|
if (row == null) return@forEach
|
||||||
|
val docName = stringFromCellHelper(row.getCell(0))
|
||||||
|
val docType = stringFromCellHelper(row.getCell(1))
|
||||||
|
val refId = stringFromCellHelper(row.getCell(2))
|
||||||
|
val url = stringFromCellHelper(row.getCell(3))
|
||||||
|
|
||||||
|
//new doc object
|
||||||
|
val doc = Document()
|
||||||
|
doc.name = docName
|
||||||
|
doc.typeOfDoc = when (docType) {
|
||||||
|
"quote" -> DocType.QUOTE
|
||||||
|
"po" -> DocType.PO
|
||||||
|
"invoice" -> DocType.INVOICE
|
||||||
|
else -> DocType.ALL
|
||||||
|
}
|
||||||
|
doc.refIdOfDoc = refId.toLong()
|
||||||
|
doc.url = url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,145 +1,321 @@
|
|||||||
package com.restapi.controllers
|
package com.restapi.controllers
|
||||||
|
|
||||||
import com.restapi.domain.*
|
import com.restapi.domain.*
|
||||||
import com.restapi.domain.PurchaseOrder
|
|
||||||
import com.restapi.domain.Quotation
|
|
||||||
import java.time.LocalDate
|
|
||||||
import com.restapi.domain.Session.database
|
import com.restapi.domain.Session.database
|
||||||
|
import net.jodah.expiringmap.ExpiringMap
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
//constants
|
//constants
|
||||||
const val IGNORE = "%"
|
const val IGNORE = "%"
|
||||||
val baseDate :LocalDate = LocalDate.MIN
|
val baseDate: LocalDate = LocalDate.of(1500, 1, 1)
|
||||||
val maxDate :LocalDate = LocalDate.MAX
|
val maxDate: LocalDate = LocalDate.of(3000, 1, 1)
|
||||||
const val RATING_MAX = 10.0
|
const val RATING_MAX = 10.0
|
||||||
const val RATING_MIN = 0.0
|
const val RATING_MIN = 0.0
|
||||||
|
|
||||||
//common filters would be used by most of the handlers
|
//common filters would be used by most of the handlers
|
||||||
//require a list of vendor ids to be passed
|
//require a list of vendor ids to be passed
|
||||||
data class CommonFilters (
|
data class CommonFilters(
|
||||||
val fromDate :LocalDate = baseDate,
|
val from: LocalDate = baseDate,
|
||||||
val toDate :LocalDate = maxDate,
|
val to: LocalDate = maxDate,
|
||||||
val vendor :List<Long>? = null,
|
val vendor: List<Long>? = null,
|
||||||
val sortAsc :Boolean = true,
|
val plant: List<Long>? = null,
|
||||||
val sortBy :String = IGNORE
|
val sortAsc: Boolean = true,
|
||||||
|
val sortBy: String = IGNORE
|
||||||
)
|
)
|
||||||
data class POFilters (
|
|
||||||
val poNumLike :String = IGNORE,
|
interface CustomFilters {}
|
||||||
val totalAmountExceeds :Long = Long.MIN_VALUE,
|
|
||||||
val totalAmountLessThan :Long = Long.MAX_VALUE,
|
data class POFilters(
|
||||||
|
val poNumLike: String = "",
|
||||||
|
val totalAmountExceeds: Long = Long.MIN_VALUE,
|
||||||
|
val totalAmountLessThan: Long = Long.MAX_VALUE,
|
||||||
val validAfter: LocalDate = baseDate,
|
val validAfter: LocalDate = baseDate,
|
||||||
val validBefore: LocalDate = maxDate,
|
val validBefore: LocalDate = maxDate,
|
||||||
val refQuotation :String = IGNORE,
|
val refQuotation: String = IGNORE,
|
||||||
|
val onlyActive: Boolean = false
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class ProductFilters(
|
||||||
|
val nameLike: String = IGNORE,
|
||||||
|
val hsnLike: String = IGNORE,
|
||||||
|
val uom: UOM = UOM.ALL,
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class DocumentFilters(
|
||||||
|
val nameLike: String = IGNORE,
|
||||||
|
val typeOfDoc: DocType = DocType.ALL,
|
||||||
|
val docDateFrom: LocalDate = baseDate,
|
||||||
|
val docDataTo: LocalDate = maxDate,
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class RFQFilters(
|
||||||
|
val validBefore: LocalDate = maxDate,
|
||||||
|
val validAfter: LocalDate = baseDate,
|
||||||
|
val reqForQuoteNumLike: String = IGNORE,
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class QuoteFilters(
|
||||||
|
val quoteNumLike: String = IGNORE,
|
||||||
|
val validBefore: LocalDate = maxDate,
|
||||||
|
val validAfter: LocalDate = baseDate,
|
||||||
|
val totalAmountExceeds: Long = Long.MIN_VALUE,
|
||||||
|
val totalAmountLessThan: Long = Long.MAX_VALUE,
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class VendorFilters(
|
||||||
|
val nameLike: String = IGNORE,
|
||||||
|
val msmeLike: String = IGNORE,
|
||||||
|
val gstNumLike: String = IGNORE,
|
||||||
|
val addressLike: String = IGNORE,
|
||||||
|
val ratingExceeds: Double = RATING_MIN,
|
||||||
|
val ratingLessThan: Double = RATING_MAX,
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class IncomingInventoryFilters(
|
||||||
|
val mrnLike: String = IGNORE,
|
||||||
|
val vehicleLike: String = IGNORE,
|
||||||
|
val vendorBillAmountExceeds: Double = Double.MIN_VALUE,
|
||||||
|
val vendorBillAmountLessThan: Double = Double.MAX_VALUE
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class OutgoingInventoryFilters(
|
||||||
|
val mdnLike: String = IGNORE,
|
||||||
|
val purposeLike: String = IGNORE,
|
||||||
|
val personLike: String = IGNORE,
|
||||||
|
val vehicleLike: String = IGNORE,
|
||||||
|
val outMode: OutMode = OutMode.ALL
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class InvoiceFilters(
|
||||||
|
val numLike: String = IGNORE,
|
||||||
|
val poNumLike: String = IGNORE,
|
||||||
|
val status: InvoiceStatus = InvoiceStatus.ALL,
|
||||||
|
val totalAmountExceeds: Double = Double.MIN_VALUE,
|
||||||
|
val totalAmountLessThan: Double = Double.MAX_VALUE
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class PaymentFilters(
|
||||||
|
val refNumberLike: String = IGNORE,
|
||||||
|
val amountExceeds: Double = Double.MIN_VALUE,
|
||||||
|
val amountLessThan: Double = Double.MAX_VALUE
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
|
||||||
|
data class FleetFilters(
|
||||||
|
val fleetNameLike: String = IGNORE
|
||||||
|
) : CustomFilters
|
||||||
|
|
||||||
|
data class ReminderLogFilters(
|
||||||
|
val reminderType: String = IGNORE,
|
||||||
|
val actedUpon: Boolean? = null,
|
||||||
|
val fleetId: Long? = null
|
||||||
)
|
)
|
||||||
data class ProductFilters (
|
|
||||||
val nameLike :String = IGNORE,
|
fun <T> applyVendorHelper(q: io.ebean.ExpressionList<T>, vids: List<Long>?) {
|
||||||
val hsnLike :String = IGNORE,
|
|
||||||
val uom :UOM = UOM.ALL,
|
|
||||||
)
|
|
||||||
data class DocumentFilters (
|
|
||||||
val nameLike :String = IGNORE,
|
|
||||||
val typeOfDoc :DocType = DocType.ALL,
|
|
||||||
)
|
|
||||||
data class RFQFilters (
|
|
||||||
val validBefore :LocalDate = maxDate,
|
|
||||||
val validAfter :LocalDate = baseDate,
|
|
||||||
val reqForQuoteNumLike :String = IGNORE,
|
|
||||||
)
|
|
||||||
data class QuoteFilters (
|
|
||||||
val quoteNumLike :String = IGNORE,
|
|
||||||
val validBefore :LocalDate = baseDate,
|
|
||||||
val validAfter :LocalDate = maxDate,
|
|
||||||
val totalAmountExceeds :Long = Long.MIN_VALUE,
|
|
||||||
val totalAmountLessThan :Long = Long.MAX_VALUE,
|
|
||||||
)
|
|
||||||
data class VendorFilters (
|
|
||||||
val nameLike :String = IGNORE,
|
|
||||||
val msmeLike :String = IGNORE,
|
|
||||||
val gstNumLike :String = IGNORE,
|
|
||||||
val addressLike :String = IGNORE,
|
|
||||||
val ratingExceeds :Double = RATING_MIN,
|
|
||||||
val ratingLessThan :Double = RATING_MAX,
|
|
||||||
)
|
|
||||||
fun<T> applyVendorHelper(q :io.ebean.ExpressionList<T>, vids :List<Long>?) {
|
|
||||||
if (vids.isNullOrEmpty()) return
|
if (vids.isNullOrEmpty()) return
|
||||||
q.apply {
|
q.eq("vendor_sys_pk", vids[0])
|
||||||
q.`in`("vendor", vids)
|
}
|
||||||
|
|
||||||
|
fun <T> applyPlantFilter(q: io.ebean.ExpressionList<T>, vids: List<Long>?) {
|
||||||
|
|
||||||
|
val v = vids?.filter { it > 0 } ?: emptyList()
|
||||||
|
if (v.isEmpty()) {
|
||||||
|
q.`in`("unloadingPlantId", Session.currentUserPlants().map { it.plantId })
|
||||||
|
} else {
|
||||||
|
q.`in`("unloadingPlantId", v.map { it.toString() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun<T> applySortHelper(q :io.ebean.ExpressionList<T>, sortBy :String, asc :Boolean) {
|
|
||||||
if(sortBy == IGNORE) return;
|
fun <T> applySortHelper(q: io.ebean.ExpressionList<T>, sortBy: String, asc: Boolean) {
|
||||||
|
if (sortBy == IGNORE) return;
|
||||||
val order = if (asc) "ASC" else "DESC"
|
val order = if (asc) "ASC" else "DESC"
|
||||||
q.orderBy("$sortBy $order")
|
q.orderBy("$sortBy $order")
|
||||||
}
|
}
|
||||||
fun<T> applyCommonFilters(q :io.ebean.ExpressionList<T>, commonFilters: CommonFilters) {
|
|
||||||
|
fun <T> applyFromToHelper(q: io.ebean.ExpressionList<T>, fromDate: LocalDate, toDate: LocalDate, colName: String) {
|
||||||
|
q.ge(colName, fromDate)
|
||||||
|
.lt(colName, toDate.plusDays(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> applyCommonFilters(q: io.ebean.ExpressionList<T>, commonFilters: CommonFilters) {
|
||||||
applyVendorHelper<T>(q, commonFilters.vendor)
|
applyVendorHelper<T>(q, commonFilters.vendor)
|
||||||
applySortHelper<T>(q, commonFilters.sortBy, commonFilters.sortAsc)
|
applySortHelper<T>(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
}
|
}
|
||||||
fun searchQuotes(commonFilters: CommonFilters, quoteFilters: QuoteFilters) : List<Quotation> {
|
|
||||||
|
fun searchQuotes(commonFilters: CommonFilters, quoteFilters: QuoteFilters): List<Quotation> {
|
||||||
val q = database.find(Quotation::class.java)
|
val q = database.find(Quotation::class.java)
|
||||||
.where()
|
.where()
|
||||||
.between("quoteDate", commonFilters.fromDate, commonFilters.toDate)
|
.ge("quoteDate", commonFilters.from)
|
||||||
.ilike("quoteNum", quoteFilters.quoteNumLike )
|
.le("quoteDate", commonFilters.to)
|
||||||
.ge("validTill",quoteFilters.validAfter)
|
.ge("validTill", quoteFilters.validAfter)
|
||||||
.le("validTill", quoteFilters.validBefore)
|
.le("validTill", quoteFilters.validBefore)
|
||||||
.le("totalAmount", quoteFilters.totalAmountLessThan)
|
|
||||||
.ge("totalAmount", quoteFilters.totalAmountExceeds)
|
.ge("totalAmount", quoteFilters.totalAmountExceeds)
|
||||||
.apply {
|
.le("totalAmount", quoteFilters.totalAmountLessThan)
|
||||||
if(!commonFilters.vendor?.isEmpty()!!){
|
.ilike("quoteNum", "%" + quoteFilters.quoteNumLike + "%")
|
||||||
commonFilters.vendor.let { this.`in`("vendor", it) }
|
applyFromToHelper(q, commonFilters.from, commonFilters.to, "quoteDate")
|
||||||
}
|
|
||||||
}
|
|
||||||
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
|
||||||
return q.findList()
|
|
||||||
}
|
|
||||||
fun searchVendors(commonFilters: CommonFilters, vendorFilters: VendorFilters) : List<Vendor> {
|
|
||||||
val q = database.find(Vendor::class.java)
|
|
||||||
.where()
|
|
||||||
.ge("rating", vendorFilters.ratingExceeds)
|
|
||||||
.le("rating", vendorFilters.ratingLessThan)
|
|
||||||
.ilike("name", vendorFilters.nameLike)
|
|
||||||
.ilike("msme", vendorFilters.msmeLike)
|
|
||||||
.ilike("gstNum", vendorFilters.gstNumLike)
|
|
||||||
.ilike("address", vendorFilters.addressLike)
|
|
||||||
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
|
||||||
return q.findList()
|
|
||||||
}
|
|
||||||
fun searchDocs(commonFilters: CommonFilters, documentFilters: DocumentFilters) : List<Document> {
|
|
||||||
val q = database.find(Document::class.java)
|
|
||||||
.where()
|
|
||||||
.apply {
|
|
||||||
if(documentFilters.typeOfDoc != DocType.ALL){
|
|
||||||
this.eq("docType", documentFilters.typeOfDoc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ilike("name", documentFilters.nameLike )
|
|
||||||
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
|
||||||
return q.findList()
|
|
||||||
}
|
|
||||||
fun searchPos(commonFilters: CommonFilters, poFilters: POFilters) : List<PurchaseOrder> {
|
|
||||||
val q = database.find(PurchaseOrder::class.java)
|
|
||||||
.where()
|
|
||||||
.between("totalAmount", poFilters.totalAmountExceeds, poFilters.totalAmountLessThan)
|
|
||||||
.between("validTill", poFilters.validAfter, poFilters.validBefore)
|
|
||||||
.ilike("poNum", poFilters.poNumLike )
|
|
||||||
.ilike("referenceQuotation", poFilters.refQuotation )
|
|
||||||
applyVendorHelper(q, commonFilters.vendor)
|
|
||||||
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
|
||||||
return q.findList()
|
|
||||||
}
|
|
||||||
fun searchRFQ(commonFilters: CommonFilters, rfqFilters: RFQFilters) : List<ReqForQuote> {
|
|
||||||
val q = database.find(ReqForQuote::class.java)
|
|
||||||
.where()
|
|
||||||
.between("validTill", rfqFilters.validAfter, rfqFilters.validBefore)
|
|
||||||
.ilike("reqForQuoteNum", rfqFilters.reqForQuoteNumLike)
|
|
||||||
applyVendorHelper(q, commonFilters.vendor)
|
applyVendorHelper(q, commonFilters.vendor)
|
||||||
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
return q.findList()
|
return q.findList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchProduct(commonFilters: CommonFilters, productFilters: ProductFilters): List<Product> {
|
fun searchVendors(commonFilters: CommonFilters, vendorFilters: VendorFilters): List<Vendor> {
|
||||||
val p = database.find(Product::class.java)
|
val q = database.find(Vendor::class.java)
|
||||||
.where()
|
.where()
|
||||||
.ilike("hsnCode", productFilters.hsnLike)
|
.ilike("name", "%" + vendorFilters.nameLike + "%")
|
||||||
.ilike("Pname", productFilters.nameLike)
|
.ilike("gstNumber", "%" + vendorFilters.gstNumLike + "%")
|
||||||
applySortHelper(p, commonFilters.sortBy, commonFilters.sortAsc)
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
return p.findList()
|
return q.findList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val productCache = ExpiringMap.builder()
|
||||||
|
.expiration(10, TimeUnit.SECONDS)
|
||||||
|
.build<String, List<Product>>()
|
||||||
|
|
||||||
|
fun searchProducts(commonFilters: CommonFilters, productFilters: ProductFilters): List<Product> {
|
||||||
|
return productCache.computeIfAbsent("$commonFilters:$productFilters:${Session.currentUser()}") {
|
||||||
|
val q = database.find(Product::class.java)
|
||||||
|
.where()
|
||||||
|
.ilike("name", "%" + productFilters.nameLike + "%")
|
||||||
|
.ilike("hsnCode", "%" + productFilters.hsnLike + "%")
|
||||||
|
|
||||||
|
if (productFilters.uom != UOM.ALL) {
|
||||||
|
q.eq("uom", productFilters.uom)
|
||||||
|
}
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
q.findList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchDocs(commonFilters: CommonFilters, documentFilters: DocumentFilters): List<Document> {
|
||||||
|
val q = database.find(Document::class.java)
|
||||||
|
.where()
|
||||||
|
.apply {
|
||||||
|
if (documentFilters.typeOfDoc != DocType.ALL) {
|
||||||
|
this.eq("docType", documentFilters.typeOfDoc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ilike("name", "%" + documentFilters.nameLike + "%")
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
applyVendorHelper(q, commonFilters.vendor)
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchPos(commonFilters: CommonFilters, poFilters0: POFilters?): List<PurchaseOrder> {
|
||||||
|
val poFilters = poFilters0 ?: POFilters()
|
||||||
|
val q = database.find(PurchaseOrder::class.java)
|
||||||
|
.where()
|
||||||
|
.apply {
|
||||||
|
if (poFilters.poNumLike.isNotEmpty()) {
|
||||||
|
ilike("poNum", "%" + poFilters.poNumLike + "%")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(poFilters.onlyActive){
|
||||||
|
q.gt("validTill", LocalDate.now().minusDays(1))
|
||||||
|
}
|
||||||
|
applyFromToHelper(q, commonFilters.from, commonFilters.to, "poDate")
|
||||||
|
applyVendorHelper(q, commonFilters.vendor)
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchRFQ(commonFilters: CommonFilters, rfqFilters: RFQFilters): List<ReqForQuote> {
|
||||||
|
val q = database.find(ReqForQuote::class.java)
|
||||||
|
.where()
|
||||||
|
.ge("validTill", rfqFilters.validAfter)
|
||||||
|
.le("validTill", rfqFilters.validBefore)
|
||||||
|
.ilike("reqForQuoteNum", "%" + rfqFilters.reqForQuoteNumLike + "%")
|
||||||
|
applyVendorHelper(q, commonFilters.vendor)
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchIncomingInventory(
|
||||||
|
commonFilters: CommonFilters,
|
||||||
|
incomingInventoryFilters: IncomingInventoryFilters
|
||||||
|
): List<IncomingInventory> {
|
||||||
|
val q = database.find(IncomingInventory::class.java).where()
|
||||||
|
applyFromToHelper(q, commonFilters.from, commonFilters.to, "date")
|
||||||
|
applyVendorHelper(q, commonFilters.vendor)
|
||||||
|
applyPlantFilter(q, commonFilters.plant)
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchOutgoingInventory(
|
||||||
|
commonFilters: CommonFilters,
|
||||||
|
outgoingInventoryFilters: OutgoingInventoryFilters
|
||||||
|
): List<OutgoingInventory> {
|
||||||
|
val q = database.find(OutgoingInventory::class.java)
|
||||||
|
.where()
|
||||||
|
// .ilike("mdn", "%" + outgoingInventoryFilters.mdnLike + "%")
|
||||||
|
// .ilike("purpose", "%" + outgoingInventoryFilters.purposeLike + "%")
|
||||||
|
// .ilike("person", "%" + outgoingInventoryFilters.personLike + "%")
|
||||||
|
//.ilike("vehicle", "%" + outgoingInventoryFilters.vehicleLike + "%")
|
||||||
|
if (outgoingInventoryFilters.outMode != OutMode.ALL) {
|
||||||
|
q.eq("outMode", outgoingInventoryFilters.outMode)
|
||||||
|
}
|
||||||
|
applyPlantFilter(q, commonFilters.plant)
|
||||||
|
|
||||||
|
applyFromToHelper(q, commonFilters.from, commonFilters.to, "date")
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchInvoices(commonFilters: CommonFilters, invoiceFilters: InvoiceFilters): List<Invoice> {
|
||||||
|
val q = database.find(Invoice::class.java)
|
||||||
|
.where()
|
||||||
|
.ilike("number", "%" + invoiceFilters.numLike + "%")
|
||||||
|
if (invoiceFilters.status != InvoiceStatus.ALL) {
|
||||||
|
q.ne("status", invoiceFilters.status)
|
||||||
|
}
|
||||||
|
applyFromToHelper(q, commonFilters.from, commonFilters.to, "date")
|
||||||
|
applyVendorHelper(q, commonFilters.vendor)
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchPayments(commonFilters: CommonFilters, paymentFilters: PaymentFilters): List<Payment> {
|
||||||
|
val q = database.find(Payment::class.java)
|
||||||
|
.where()
|
||||||
|
.ilike("refNumber", "%" + paymentFilters.refNumberLike + "%")
|
||||||
|
// .ge("amount", paymentFilters.amountExceeds)
|
||||||
|
//.le("amount", paymentFilters.amountLessThan)
|
||||||
|
applyFromToHelper(q, commonFilters.from, commonFilters.to, "date")
|
||||||
|
applyVendorHelper(q, commonFilters.vendor)
|
||||||
|
applySortHelper(q, commonFilters.sortBy, commonFilters.sortAsc)
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchFleets(filters: CommonFilters, fleetFilters: FleetFilters): List<Fleet> {
|
||||||
|
val q = database.find(Fleet::class.java)
|
||||||
|
.where()
|
||||||
|
.ilike("name", "%" + fleetFilters.fleetNameLike + "%")
|
||||||
|
|
||||||
|
// q.raw("(insurance_renewal_date >= ? and insurance_renewal_date <= ?)" +
|
||||||
|
// "or (pollution_renewal_date >= ? and pollution_renewal_date <= ?)" +
|
||||||
|
// "or (fitness_renewal_date >= ? and fitness_renewal_date <= ?)",
|
||||||
|
// filters.from, filters.to, filters.from, filters.to, filters.from, filters.to
|
||||||
|
// )
|
||||||
|
// applyFromToHelper(q, filters.from, filters.to, "insuranceRenewalDate")
|
||||||
|
// applyFromToHelper(q, filters.from, filters.to, "pollutionRenewalDate")
|
||||||
|
// applyFromToHelper(q, filters.from, filters.to, "fitnessRenewalDate")
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchReminderLogs(filters: CommonFilters, reminderLogFilters: ReminderLogFilters): List<ReminderLog> {
|
||||||
|
val q = database.find(ReminderLog::class.java)
|
||||||
|
.where()
|
||||||
|
.ilike("reminder_type", reminderLogFilters.reminderType)
|
||||||
|
if (reminderLogFilters.actedUpon != null) {
|
||||||
|
q.eq("acted_upon", reminderLogFilters.actedUpon)
|
||||||
|
}
|
||||||
|
if (reminderLogFilters.fleetId != null) {
|
||||||
|
q.eq("fleet_sys_pk", reminderLogFilters.fleetId)
|
||||||
|
}
|
||||||
|
return q.findList()
|
||||||
|
}
|
||||||
|
|
||||||
|
//if date is null then fromtoheper drops that///
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,287 @@
|
|||||||
|
package com.restapi.controllers
|
||||||
|
|
||||||
|
import com.restapi.domain.*
|
||||||
|
import io.javalin.http.Context
|
||||||
|
import io.javalin.http.HttpStatus
|
||||||
|
import io.javalin.http.NotFoundResponse
|
||||||
|
import io.javalin.http.bodyAsClass
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
object FleetCtrl {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val fleet = ctx.bodyAsClass<Fleet>()
|
||||||
|
Session.database.save(fleet)
|
||||||
|
ctx.json(fleet).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val fleet = Session.database.find(Fleet::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No fleet found with id $id")
|
||||||
|
ctx.json(fleet).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class FLTF(val common: CommonFilters, val fleetFilters: FleetFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<FLTF>()
|
||||||
|
val fleets = searchFleets(filters.common, filters.fleetFilters)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
exportFleets(fleets)
|
||||||
|
val inputStream = FileInputStream("./excel/Fleets.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(fleets).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val fleet =
|
||||||
|
Session.database.find(Fleet::class.java, id) ?: throw NotFoundResponse("fleet not found for $id")
|
||||||
|
val updatedFleet = ctx.bodyAsClass<Fleet>()
|
||||||
|
fleet.patchValues(updatedFleet)
|
||||||
|
fleet.update()
|
||||||
|
ctx.json(fleet).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
object FleetTypeCtrl {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val fleetType = ctx.bodyAsClass<FleetType>()
|
||||||
|
Session.database.save(fleetType)
|
||||||
|
ctx.json(fleetType).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val fleetType = Session.database.find(FleetType::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No fleetType found with id $id")
|
||||||
|
ctx.json(fleetType).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val fleetTypes = Session.database.find(FleetType::class.java).findList()
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
// exportFleetTypes(fleetTypes)
|
||||||
|
val inputStream = FileInputStream("./excel/FleetTypes.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(fleetTypes).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val fleetType =
|
||||||
|
Session.database.find(FleetType::class.java, id) ?: throw NotFoundResponse("fleetType not found for $id")
|
||||||
|
val updatedFleetType = ctx.bodyAsClass<FleetType>()
|
||||||
|
fleetType.patchValues(updatedFleetType)
|
||||||
|
fleetType.update()
|
||||||
|
ctx.json(fleetType).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object RenewalCtrl {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val renewal = ctx.bodyAsClass<Renewal>()
|
||||||
|
Session.database.save(renewal)
|
||||||
|
ctx.json(renewal).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val renewal = Session.database.find(Renewal::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No renewal found with id $id")
|
||||||
|
ctx.json(renewal).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
//data class RNLF(val common: CommonFilters, val renewalFilters: RenewalFilters)
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
// val filters = ctx.bodyAsClass<FLTF>()
|
||||||
|
// val renewals = searchRenewals(filters.common, filters.renewalFilters)
|
||||||
|
val renewals = Session.database.find(Renewal::class.java).findList()
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
// exportRenewals(renewals)
|
||||||
|
val inputStream = FileInputStream("./excel/Renewals.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(renewals).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val renewal =
|
||||||
|
Session.database.find(Renewal::class.java, id) ?: throw NotFoundResponse("renewal not found for $id")
|
||||||
|
val updatedRenewal = ctx.bodyAsClass<Renewal>()
|
||||||
|
renewal.patchValues(updatedRenewal)
|
||||||
|
renewal.update()
|
||||||
|
ctx.json(renewal).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReminderCtrl {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val renewal = ctx.bodyAsClass<Reminder>()
|
||||||
|
Session.database.save(renewal)
|
||||||
|
val entry = ReminderLog()
|
||||||
|
entry.apply {
|
||||||
|
reminder = renewal
|
||||||
|
reminderDate = renewal.nextRenewalDate
|
||||||
|
reminderType = renewal.type
|
||||||
|
fleet = renewal.fleet
|
||||||
|
amount = 0.0
|
||||||
|
actedUpon = false
|
||||||
|
}
|
||||||
|
ReminderLogCtrl.create(entry)
|
||||||
|
ctx.json(renewal).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllByFleetId(ctx: Context) {
|
||||||
|
val fleetId = ctx.pathParam("id").toLong()
|
||||||
|
val history = Session.database.find(Reminder::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("fleet_sys_pk", fleetId)
|
||||||
|
.findList()
|
||||||
|
ctx.json(history).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val renewal = Session.database.find(Reminder::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No renewal found with id $id")
|
||||||
|
ctx.json(renewal).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
//data class RNLF(val common: CommonFilters, val renewalFilters: ReminderFilters)
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
// val filters = ctx.bodyAsClass<FLTF>()
|
||||||
|
// val renewals = searchReminders(filters.common, filters.renewalFilters)
|
||||||
|
val renewals = Session.database.find(Reminder::class.java).findList()
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
// exportReminders(renewals)
|
||||||
|
val inputStream = FileInputStream("./excel/Reminders.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(renewals).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val renewal =
|
||||||
|
Session.database.find(Reminder::class.java, id) ?: throw NotFoundResponse("renewal not found for $id")
|
||||||
|
val updatedReminder = ctx.bodyAsClass<Reminder>()
|
||||||
|
renewal.patchValues(updatedReminder)
|
||||||
|
renewal.update()
|
||||||
|
ctx.json(renewal).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ReminderLogCtrl {
|
||||||
|
fun create(entry: ReminderLog) {
|
||||||
|
// val renewal = ctx.bodyAsClass<ReminderLog>()
|
||||||
|
|
||||||
|
Session.database.save(entry)
|
||||||
|
return
|
||||||
|
//ctx.json(renewal).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Done(
|
||||||
|
val logId: Long,
|
||||||
|
val reminderId: Long,
|
||||||
|
val renewalDate: LocalDate,
|
||||||
|
val nextRenewalDate: LocalDate,
|
||||||
|
val amount: Double,
|
||||||
|
val documents: List<String>?
|
||||||
|
)
|
||||||
|
|
||||||
|
fun done(ctx: Context) {
|
||||||
|
val req = ctx.bodyAsClass<Done>()
|
||||||
|
val reminder =
|
||||||
|
Session.database.find(Reminder::class.java, req.reminderId) ?: throw NotFoundResponse("No Reminder found")
|
||||||
|
//update reminder
|
||||||
|
reminder.apply {
|
||||||
|
lastRenewalDate = req.renewalDate
|
||||||
|
nextRenewalDate = req.nextRenewalDate
|
||||||
|
}
|
||||||
|
reminder.update()
|
||||||
|
val entry = Session.database.find(ReminderLog::class.java, req.logId) ?: throw NotFoundResponse("Log not found")
|
||||||
|
entry.apply {
|
||||||
|
actedUpon = true
|
||||||
|
documents = req.documents
|
||||||
|
amount = req.amount
|
||||||
|
}
|
||||||
|
entry.update()
|
||||||
|
ctx.json(entry).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllByFleetId(ctx: Context) {
|
||||||
|
val fleetId = ctx.pathParam("id").toLong()
|
||||||
|
val history = Session.database.find(ReminderLog::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("fleet_sys_pk", fleetId)
|
||||||
|
.findList()
|
||||||
|
ctx.json(history).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val renewal = Session.database.find(ReminderLog::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No renewal found with id $id")
|
||||||
|
ctx.json(renewal).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class LOGF(val common: CommonFilters, val reminderLogFilters: ReminderLogFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<LOGF>()
|
||||||
|
val entries = searchReminderLogs(filters.common, filters.reminderLogFilters)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
exportReminderLogs(entries)
|
||||||
|
val inputStream = FileInputStream("./excel/ReminderLogs.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(entries).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val renewal =
|
||||||
|
Session.database.find(ReminderLog::class.java, id) ?: throw NotFoundResponse("renewal not found for $id")
|
||||||
|
val updatedReminderLog = ctx.bodyAsClass<ReminderLog>()
|
||||||
|
renewal.patchValues(updatedReminderLog)
|
||||||
|
renewal.update()
|
||||||
|
ctx.json(renewal).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
package com.restapi.controllers
|
||||||
|
|
||||||
|
import com.restapi.domain.*
|
||||||
|
import com.restapi.domain.Session.database
|
||||||
|
import com.restapi.integ.logger
|
||||||
|
import io.javalin.http.*
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
object IncomingInventoryCtrl {
|
||||||
|
fun plantsForUser(ctx: Context) {
|
||||||
|
ctx.json(
|
||||||
|
Session.currentUserPlants()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updatePlant(ctx: Context) {
|
||||||
|
val p = ctx.bodyAsClass<Plant>()
|
||||||
|
database.find(Plant::class.java, ctx.pathParam("id"))?.let {
|
||||||
|
it.patch(p)
|
||||||
|
}
|
||||||
|
ctx.json(
|
||||||
|
Session.currentUserPlants()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val ticket = ctx.bodyAsClass<IncomingInventory>()
|
||||||
|
database.save(ticket)
|
||||||
|
keepTrackOfPoQty(ticket)
|
||||||
|
ctx.json(ticket).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val ticket =
|
||||||
|
database.find(IncomingInventory::class.java, id) ?: throw NotFoundResponse("quote not found for $id")
|
||||||
|
val updatedTicket = ctx.bodyAsClass<IncomingInventory>()
|
||||||
|
ticket.patchValues(updatedTicket)
|
||||||
|
ticket.update()
|
||||||
|
keepTrackOfPoQty(ticket)
|
||||||
|
ctx.json(ticket).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun keepTrackOfPoQty(ticket: IncomingInventory) {
|
||||||
|
ticket.products?.forEach { incomingProduct ->
|
||||||
|
if (incomingProduct.poId != null) {
|
||||||
|
database.find(PurchaseOrder::class.java, incomingProduct.poId)?.let { po ->
|
||||||
|
logger.warn("found po for ${incomingProduct.poId} => ${po.poNum}")
|
||||||
|
po.products.forEach { poProduct ->
|
||||||
|
if (poProduct.productId == incomingProduct.productId) {
|
||||||
|
logger.warn("for ${ticket.mrn} , product ${poProduct.productId} add to po-qty ${incomingProduct.receivedQty}")
|
||||||
|
//remove existing entry for same mrn and product id
|
||||||
|
poProduct.receivedVoucher.removeIf {
|
||||||
|
it.productId == incomingProduct.productId
|
||||||
|
&& it.plantId == ticket.unloadingPlantId
|
||||||
|
&& it.ticket == ticket.mrn
|
||||||
|
}
|
||||||
|
poProduct.receivedVoucher.add(
|
||||||
|
ReceivedVoucher(
|
||||||
|
ticket = ticket.mrn!!,
|
||||||
|
productName = poProduct.productName,
|
||||||
|
productId = poProduct.productId,
|
||||||
|
qty = incomingProduct.receivedQty,
|
||||||
|
plantId = ticket.unloadingPlantId!!,
|
||||||
|
ticketDate = ticket.date!!
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
logger.warn("no match for ${poProduct.productId} and ${incomingProduct.productId}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
po.update()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("poId is missing for $incomingProduct")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val ticket = database.find(IncomingInventory::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No incoming inventory ticket found with id $id")
|
||||||
|
ctx.json(ticket).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class IIF(val common: CommonFilters, val incomingInventoryFilters: IncomingInventoryFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<IIF>()
|
||||||
|
val tickets = searchIncomingInventory(filters.common, filters.incomingInventoryFilters)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
exportIncomingInventory(tickets)
|
||||||
|
val inputStream = FileInputStream("./excel/IncomingInventory.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(tickets).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNextNum(ctx: Context) {
|
||||||
|
val prefix = "MRN/"
|
||||||
|
val plantId = ctx.queryParam("plantId") ?: throw BadRequestResponse("plantId not sent")
|
||||||
|
val plant = database.find(Plant::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("plantId", plantId)
|
||||||
|
.findOne() ?: throw BadRequestResponse("plant missing for $plantId")
|
||||||
|
val inventoryPrefix = plant.prefixes?.get("INBOUND") ?: prefix
|
||||||
|
|
||||||
|
val cnt = (database.find(IncomingInventory::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("unloadingPlantId", plantId)
|
||||||
|
.findCount() + 1)
|
||||||
|
.toString()
|
||||||
|
.padStart(6, '0')
|
||||||
|
val seq = SequenceNumber(inventoryPrefix + cnt)
|
||||||
|
ctx.json(seq).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object OutgoingInventoryCtrl {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val ticket = ctx.bodyAsClass<OutgoingInventory>()
|
||||||
|
database.save(ticket)
|
||||||
|
ctx.json(ticket).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val ticket =
|
||||||
|
database.find(OutgoingInventory::class.java, id) ?: throw NotFoundResponse("quote not found for $id")
|
||||||
|
val updatedTicket = ctx.bodyAsClass<OutgoingInventory>()
|
||||||
|
ticket.patchValues(updatedTicket)
|
||||||
|
ticket.update()
|
||||||
|
ctx.json(ticket).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val ticket = database.find(OutgoingInventory::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No incoming inventory ticket found with id $id")
|
||||||
|
ctx.json(ticket).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class OIF(val common: CommonFilters, val outgoingInventoryFilters: OutgoingInventoryFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<OIF>()
|
||||||
|
val tickets = searchOutgoingInventory(filters.common, filters.outgoingInventoryFilters)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
exportOutgoingInventory(tickets)
|
||||||
|
val inputStream = FileInputStream("./excel/OutgoingInventory.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(tickets).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNextNum(ctx: Context) {
|
||||||
|
val prefix = "MDN/"
|
||||||
|
val plantId = ctx.queryParam("plantId") ?: throw BadRequestResponse("plantId not sent")
|
||||||
|
val plant = database.find(Plant::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("plantId", plantId)
|
||||||
|
.findOne() ?: throw BadRequestResponse("plant missing for $plantId")
|
||||||
|
val inventoryPrefix = plant.prefixes?.get("OUTBOUND") ?: prefix
|
||||||
|
|
||||||
|
val cnt = (database.find(OutgoingInventory::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("unloadingPlantId", plantId)
|
||||||
|
.findCount() + 1)
|
||||||
|
.toString()
|
||||||
|
.padStart(6, '0')
|
||||||
|
val seq = SequenceNumber(inventoryPrefix + cnt)
|
||||||
|
ctx.json(seq).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.restapi.controllers
|
||||||
|
|
||||||
|
import com.restapi.domain.Invoice
|
||||||
|
import com.restapi.domain.InvoiceStatus
|
||||||
|
import com.restapi.domain.Payment
|
||||||
|
import com.restapi.domain.Session
|
||||||
|
import io.javalin.http.Context
|
||||||
|
import io.javalin.http.HttpStatus
|
||||||
|
import io.javalin.http.NotFoundResponse
|
||||||
|
import io.javalin.http.bodyAsClass
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
object PaymentCtrl {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val pmt = ctx.bodyAsClass(Payment::class.java)
|
||||||
|
//update the status of invoices pertaining to payment.vendor
|
||||||
|
val vendors: List<Long>? = pmt.vendor?.let { listOf(it.sysPk) }
|
||||||
|
val invoices = searchInvoices(
|
||||||
|
CommonFilters(sortBy = "date", sortAsc = true, vendor = vendors),
|
||||||
|
InvoiceFilters(status = InvoiceStatus.PAID_FULL)
|
||||||
|
)
|
||||||
|
// println(invoices)
|
||||||
|
//pmt.invoicesAffected = mutableMapOf()
|
||||||
|
var totalAmount = pmt.amount
|
||||||
|
var totalDeduct = 0.0
|
||||||
|
for (invoice in invoices) {
|
||||||
|
val deduct = Math.min(totalAmount, invoice.totalAmount)
|
||||||
|
invoice.totalAmount -= deduct
|
||||||
|
totalDeduct += deduct
|
||||||
|
totalAmount -= deduct
|
||||||
|
if (invoice.totalAmount <= 0.0) {
|
||||||
|
invoice.status = InvoiceStatus.PAID_FULL
|
||||||
|
} else {
|
||||||
|
invoice.status = InvoiceStatus.PAID_SOME
|
||||||
|
}
|
||||||
|
//println(invoice)
|
||||||
|
Session.database.update(invoice)
|
||||||
|
pmt.invoicesAffected?.put(invoice.sysPk, deduct)
|
||||||
|
println(pmt.invoicesAffected)
|
||||||
|
if (totalAmount <= 0.0) break
|
||||||
|
}
|
||||||
|
pmt.amountDeducted = totalDeduct
|
||||||
|
pmt.excessAmount = pmt.amount - pmt.amountDeducted!!
|
||||||
|
Session.database.save(pmt)
|
||||||
|
ctx.json(pmt).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val pmt = Session.database.find(Payment::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No payment found for this id $id")
|
||||||
|
val invoiceDeductMap = pmt.invoicesAffected
|
||||||
|
for (entry in invoiceDeductMap?.entries!!.iterator()) {
|
||||||
|
val inv = Session.database.find(Invoice::class.java, entry.key)
|
||||||
|
?: throw NotFoundResponse("No invoice found for $entry.key")
|
||||||
|
inv.totalAmount += entry.value
|
||||||
|
inv.status = InvoiceStatus.PAID_SOME
|
||||||
|
Session.database.update(inv)
|
||||||
|
}
|
||||||
|
Session.database.delete(pmt)
|
||||||
|
ctx.json(pmt).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val pmt = Session.database.find(Payment::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No payment found for this id $id")
|
||||||
|
ctx.json(pmt).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PMTF(val common: CommonFilters, val paymentFilters: PaymentFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<PMTF>()
|
||||||
|
val payments = searchPayments(filters.common, filters.paymentFilters)
|
||||||
|
// println(payments)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
exportPayments(payments)
|
||||||
|
val inputStream = FileInputStream("./excel/Payments.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(payments).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val pmt =
|
||||||
|
Session.database.find(Payment::class.java, id) ?: throw NotFoundResponse("payment not found for $id")
|
||||||
|
val updatedPayment = ctx.bodyAsClass<Payment>()
|
||||||
|
pmt.patchValues(updatedPayment)
|
||||||
|
pmt.update()
|
||||||
|
ctx.json(pmt).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package com.restapi.controllers
|
||||||
|
|
||||||
|
import com.restapi.domain.Product
|
||||||
|
import com.restapi.domain.PurchaseOrder
|
||||||
|
import com.restapi.domain.Session
|
||||||
|
import com.restapi.domain.Vendor
|
||||||
|
import io.javalin.http.*
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
object ProductCtrl {
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val product = Session.database.find(Product::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("sys_pk", id.toLong())
|
||||||
|
.findOne()
|
||||||
|
?: throw NotFoundResponse("Product not found for $id")
|
||||||
|
ctx.json(product).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PF(val common: CommonFilters, val productFilters: ProductFilters)
|
||||||
|
data class GetPrice(val productId: Long, val vendor: Long, val po: Long?)
|
||||||
|
|
||||||
|
fun getPrice(ctx: Context) {
|
||||||
|
val gp = ctx.bodyAsClass<GetPrice>()
|
||||||
|
val vendor = Session.database.find(Vendor::class.java, gp.vendor) ?: throw BadRequestResponse("vendor not found for ${gp.vendor}")
|
||||||
|
val product = Session.database.find(Product::class.java, gp.productId) ?: throw BadRequestResponse("product not found for ${gp.productId}")
|
||||||
|
val poProduct = if (gp.po != null) {
|
||||||
|
Session.database.find(PurchaseOrder::class.java, gp.po)?.products?.firstOrNull { it.productId == product.sysPk }
|
||||||
|
} else {
|
||||||
|
Session.database.find(PurchaseOrder::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("vendor", vendor)
|
||||||
|
.findList()
|
||||||
|
.flatMap { it.products }
|
||||||
|
.firstOrNull { it.productId == product.sysPk }
|
||||||
|
|
||||||
|
}
|
||||||
|
ctx.json(
|
||||||
|
poProduct ?: throw BadRequestResponse("price not found for this vendor and product and po")
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<PF>()
|
||||||
|
val prods = searchProducts(filters.common, filters.productFilters)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel != null) {
|
||||||
|
exportProds(prods)
|
||||||
|
val inputStream = FileInputStream("./excel/Products.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ctx.json(prods).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val product = ctx.bodyAsClass<Product>()
|
||||||
|
Session.database.save(product)
|
||||||
|
ctx.json(product).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val prod = Session.database.find(Product::class.java, id) ?: throw NotFoundResponse("no product found with id $id")
|
||||||
|
Session.database.delete(prod)
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun patch(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val patchValues = ctx.bodyAsClass<Map<String, Any>>()
|
||||||
|
Session.database.beginTransaction().use {
|
||||||
|
patchValues.entries.forEach { en ->
|
||||||
|
val key = en.key
|
||||||
|
val value = en.value
|
||||||
|
Session.database.sqlUpdate("update products set $key = ? where id = ?").apply {
|
||||||
|
setParameter(1, value)
|
||||||
|
setParameter(2, id)
|
||||||
|
execute()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val product = Session.database.find(Product::class.java, id) ?: throw NotFoundResponse("product not found for $id")
|
||||||
|
val updatedProduct = ctx.bodyAsClass<Product>()
|
||||||
|
product.patchValues(updatedProduct)
|
||||||
|
product.update()
|
||||||
|
ctx.json(product).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
|
||||||
|
val patchValues = mapOf("name" to 1)
|
||||||
|
val id = 1;
|
||||||
|
Session.database.beginTransaction().use {
|
||||||
|
patchValues.entries.forEach { en ->
|
||||||
|
val key = en.key
|
||||||
|
val value = en.value
|
||||||
|
|
||||||
|
Session.database.sqlUpdate("update product set $key = ? where sys_pk = ?").apply {
|
||||||
|
setParameter(1, value)
|
||||||
|
setParameter(2, id)
|
||||||
|
|
||||||
|
execute()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,269 @@
|
|||||||
|
package com.restapi.controllers
|
||||||
|
|
||||||
|
import com.restapi.domain.*
|
||||||
|
import io.javalin.http.Context
|
||||||
|
import io.javalin.http.HttpStatus
|
||||||
|
import io.javalin.http.NotFoundResponse
|
||||||
|
import io.javalin.http.bodyAsClass
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
object PurchaseOrderCtrl {
|
||||||
|
|
||||||
|
fun getNextNum(ctx: Context) {
|
||||||
|
val prefix = "PO/"
|
||||||
|
val cnt = (Session.database.find(PurchaseOrder::class.java)
|
||||||
|
.findCount() + 1)
|
||||||
|
.toString()
|
||||||
|
.padStart(6, '0')
|
||||||
|
val seq = SequenceNumber(prefix + cnt)
|
||||||
|
ctx.json(seq).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val po = Session.database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
|
||||||
|
ctx.json(po).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PoFilterQuery(val common: CommonFilters, val poFilters: POFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<PoFilterQuery>()
|
||||||
|
val pos = searchPos(filters.common, filters.poFilters)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel != null) {
|
||||||
|
exportPos(pos)
|
||||||
|
val inputStream = FileInputStream("./excel/Pos.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(pos).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val po = ctx.bodyAsClass<PurchaseOrder>()
|
||||||
|
val prods = po.products
|
||||||
|
if (prods.isEmpty()) {
|
||||||
|
ctx.json(mapOf("error" to "empty product list")).status(HttpStatus.BAD_REQUEST)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Session.database.save(po)
|
||||||
|
ctx.json(po).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createBatch(ctx: Context) {
|
||||||
|
val pos = ctx.bodyAsClass<List<PurchaseOrder>>()
|
||||||
|
val txn = Session.database.beginTransaction()
|
||||||
|
try {
|
||||||
|
txn.isBatchMode = true
|
||||||
|
for (po in pos) Session.database.save(po)
|
||||||
|
txn.commit()
|
||||||
|
ctx.status(HttpStatus.CREATED).result("POS Created")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
txn.rollback()
|
||||||
|
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR).result("Pos Creation failed" + e.message)
|
||||||
|
} finally {
|
||||||
|
txn.end()
|
||||||
|
}
|
||||||
|
ctx.result("pos batch created").status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun approve(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val po = Session.database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
|
||||||
|
po.approvalStatus = ApprovalStatus.APPROVED
|
||||||
|
po.save()
|
||||||
|
ctx.json(po).status(HttpStatus.CREATED)
|
||||||
|
//reject all other pos pertaining to the same tx ??
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reject(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val po = Session.database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
|
||||||
|
po.apply {
|
||||||
|
approvalStatus = ApprovalStatus.REJECTED
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
ctx.json(po).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun quoteReference(ctx: Context) {
|
||||||
|
//gets the quote reference on which this po is based on
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val quote = Session.database.find(Quotation::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("referenceQuotation", id)
|
||||||
|
?: throw NotFoundResponse("reference quotation not found for po $id")
|
||||||
|
ctx.json(quote)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val po = Session.database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("po not found for $id")
|
||||||
|
val updatedPo = ctx.bodyAsClass<PurchaseOrder>()
|
||||||
|
po.patchValues(updatedPo)
|
||||||
|
po.update()
|
||||||
|
ctx.json(po).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val po = Session.database.find(PurchaseOrder::class.java, id) ?: throw NotFoundResponse("no po found with id $id")
|
||||||
|
Session.database.delete(po)
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object QuotationCtrl {
|
||||||
|
fun getNextNum(ctx: Context) {
|
||||||
|
val prefix = "QUOTE/"
|
||||||
|
val cnt = Session.database.find(Quotation::class.java)
|
||||||
|
.findCount()
|
||||||
|
.toString()
|
||||||
|
.padStart(6, '0')
|
||||||
|
val seq = SequenceNumber(prefix + cnt)
|
||||||
|
ctx.json(seq).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val quote = Session.database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for $id")
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
ctx.json(quote)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class QF(val common: CommonFilters, val quoteFilters: QuoteFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<QF>()
|
||||||
|
val excel: String? = ctx.queryParam("excel")
|
||||||
|
val quotes = searchQuotes(filters.common, filters.quoteFilters)
|
||||||
|
if (excel != null) {
|
||||||
|
exportQuotations(quotes)
|
||||||
|
val inputStream = FileInputStream("./excel/Quotes.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(quotes).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val quote = ctx.bodyAsClass<Quotation>()
|
||||||
|
//validation
|
||||||
|
val prods = quote.products
|
||||||
|
if (prods.isEmpty()) {
|
||||||
|
ctx.json(mapOf("error" to "empty product list")).status(HttpStatus.BAD_REQUEST)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Session.database.save(quote)
|
||||||
|
ctx.json(quote).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createBatch(ctx: Context) {
|
||||||
|
val quotes = ctx.bodyAsClass<List<Quotation>>()
|
||||||
|
val txn = Session.database.beginTransaction()
|
||||||
|
try {
|
||||||
|
txn.isBatchMode = true
|
||||||
|
for (quote in quotes) Session.database.save(quote)
|
||||||
|
txn.commit()
|
||||||
|
ctx.status(HttpStatus.CREATED).result("Quotes Created")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
txn.rollback()
|
||||||
|
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR).result("Quotes Creation failed" + e.message)
|
||||||
|
} finally {
|
||||||
|
txn.end()
|
||||||
|
}
|
||||||
|
ctx.result("Quotes batch created").status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val quote = Session.database.find(Quotation::class.java, id) ?: throw NotFoundResponse("no quote found with id $id")
|
||||||
|
Session.database.delete(quote)
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val quote = Session.database.find(Quotation::class.java, id) ?: throw NotFoundResponse("quote not found for $id")
|
||||||
|
val updatedQuote = ctx.bodyAsClass<Quotation>()
|
||||||
|
quote.patchValues(updatedQuote)
|
||||||
|
quote.update()
|
||||||
|
ctx.json(quote).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object RequestForQuote {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val rfq = ctx.bodyAsClass<ReqForQuote>()
|
||||||
|
Session.database.save(rfq)
|
||||||
|
//ctx.result("request for quote created")
|
||||||
|
//ctx.json(rfq)
|
||||||
|
ctx.status(HttpStatus.CREATED)
|
||||||
|
ctx.json("asss")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val rfq = Session.database.find(ReqForQuote::class.java, id)
|
||||||
|
?: throw NotFoundResponse("request for quote not found for id $id")
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
ctx.json(rfq)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
//shuld we compare the new body fields with preexisting ones and prepare a sql query to update those fields??
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object InvoiceCtrl {
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val invoice = ctx.bodyAsClass<Invoice>()
|
||||||
|
Session.database.save(invoice)
|
||||||
|
ctx.json(invoice).status(HttpStatus.CREATED)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val invoice = Session.database.find(Invoice::class.java, id)
|
||||||
|
?: throw NotFoundResponse("No invoice found with id $id")
|
||||||
|
ctx.json(invoice).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class INVF(val common: CommonFilters, val invoiceFilters: InvoiceFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<INVF>()
|
||||||
|
val invoices = searchInvoices(filters.common, filters.invoiceFilters)
|
||||||
|
val excel = ctx.queryParam("excel")
|
||||||
|
if (excel !== null) {
|
||||||
|
exportInvoices(invoices)
|
||||||
|
val inputStream = FileInputStream("./excel/Invoices.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(invoices).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val invoice =
|
||||||
|
Session.database.find(Invoice::class.java, id) ?: throw NotFoundResponse("invoice not found for $id")
|
||||||
|
val updatedPayment = ctx.bodyAsClass<Invoice>()
|
||||||
|
invoice.patchValues(updatedPayment)
|
||||||
|
invoice.update()
|
||||||
|
ctx.json(invoice).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNextNum(ctx: Context) {
|
||||||
|
val prefix = "INV/"
|
||||||
|
val cnt = Session.database.find(Invoice::class.java)
|
||||||
|
.findCount()
|
||||||
|
.toString()
|
||||||
|
.padStart(6, '0')
|
||||||
|
val seq = SequenceNumber(prefix + cnt)
|
||||||
|
ctx.json(seq).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.restapi.controllers
|
||||||
|
|
||||||
|
import com.restapi.domain.PurchaseOrder
|
||||||
|
import com.restapi.domain.Quotation
|
||||||
|
import com.restapi.domain.Session
|
||||||
|
import com.restapi.domain.Vendor
|
||||||
|
import io.javalin.http.Context
|
||||||
|
import io.javalin.http.HttpStatus
|
||||||
|
import io.javalin.http.NotFoundResponse
|
||||||
|
import io.javalin.http.bodyAsClass
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
object VendorCtrl {
|
||||||
|
val logger = LoggerFactory.getLogger("Vendor")
|
||||||
|
fun get(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val vendor = Session.database.find(Vendor::class.java, id) ?: throw NotFoundResponse("no vendor found with id $id")
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
ctx.json(vendor)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class VF(val common: CommonFilters, val vendorFilters: VendorFilters)
|
||||||
|
|
||||||
|
fun getAll(ctx: Context) {
|
||||||
|
val filters = ctx.bodyAsClass<VF>()
|
||||||
|
val excel: String? = ctx.queryParam("excel")
|
||||||
|
val vendors = searchVendors(filters.common, filters.vendorFilters)
|
||||||
|
if (excel !== null) {
|
||||||
|
exportVendors(vendors)
|
||||||
|
val inputStream = FileInputStream("./excel/VendorList.xls")
|
||||||
|
ctx.result(inputStream).status(HttpStatus.OK)
|
||||||
|
} else {
|
||||||
|
ctx.json(vendors).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createBatch(ctx: Context) {
|
||||||
|
val vendors = ctx.bodyAsClass<List<Vendor>>()
|
||||||
|
Session.database.saveAll(vendors)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(ctx: Context) {
|
||||||
|
val vendor = ctx.bodyAsClass<Vendor>()
|
||||||
|
Session.database.save(vendor)
|
||||||
|
ctx.status(HttpStatus.CREATED)
|
||||||
|
ctx.json(vendor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val vendor = Session.database.find(Vendor::class.java, id) ?: throw NotFoundResponse("vendor not found for $id")
|
||||||
|
val updatedVendor = ctx.bodyAsClass<Vendor>()
|
||||||
|
vendor.patchValues(updatedVendor)
|
||||||
|
vendor.update()
|
||||||
|
ctx.json(vendor).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val vendor = Session.database.find(Vendor::class.java, id) ?: throw NotFoundResponse("no vendor found with id $id")
|
||||||
|
Session.database.delete(vendor)
|
||||||
|
ctx.status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getQuotes(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val quotes = Session.database.find(Quotation::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("vendor", Session.database.find(Vendor::class.java, id) ?: throw NotFoundResponse("vendor not found for $id"))
|
||||||
|
.findList()
|
||||||
|
ctx.json(quotes).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPos(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id").toLong()
|
||||||
|
val pos = Session.database.find(PurchaseOrder::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("vendor", Session.database.find(Vendor::class.java, id) ?: throw NotFoundResponse("vendor not found for $id"))
|
||||||
|
.findList()
|
||||||
|
ctx.json(pos).status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rate(ctx: Context) {
|
||||||
|
val id = ctx.pathParam("id")
|
||||||
|
val rating1 = ctx.pathParam("rating").toDouble()
|
||||||
|
|
||||||
|
Session.database.find(Vendor::class.java, id)?.let {
|
||||||
|
it.rating = rating1
|
||||||
|
it.save()
|
||||||
|
} ?: throw NotFoundResponse("vendor not found for id $id")
|
||||||
|
|
||||||
|
|
||||||
|
ctx.result("rating changed").status(HttpStatus.OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package com.restapi.domain
|
||||||
|
|
||||||
|
import io.ebean.annotation.DbArray
|
||||||
|
import io.ebean.annotation.DbJsonB
|
||||||
|
import java.time.LocalDate
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.ManyToOne
|
||||||
|
|
||||||
|
data class FR(val renewal: String, val date: LocalDate)
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class Fleet : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: Fleet) {
|
||||||
|
this.name = updated.name
|
||||||
|
this.type = updated.type
|
||||||
|
this.regNumber = updated.regNumber
|
||||||
|
this.model = updated.model
|
||||||
|
this.make = updated.make
|
||||||
|
this.driver = updated.driver
|
||||||
|
this.driverContact = updated.driverContact
|
||||||
|
this.mileage = updated.mileage
|
||||||
|
this.cost = updated.cost
|
||||||
|
this.insuranceRenewalDate = updated.insuranceRenewalDate
|
||||||
|
this.pollutionRenewalDate = updated.pollutionRenewalDate
|
||||||
|
this.fitnessRenewalDate = updated.fitnessRenewalDate
|
||||||
|
this.renewals = updated.renewals
|
||||||
|
this.regDate = updated.regDate
|
||||||
|
}
|
||||||
|
|
||||||
|
var name: String = ""
|
||||||
|
var type: String = ""
|
||||||
|
var regNumber: String = ""
|
||||||
|
var regDate: LocalDate? = null
|
||||||
|
var model: String = ""
|
||||||
|
var make: String = ""
|
||||||
|
var driver: String = ""
|
||||||
|
var driverContact: String = ""
|
||||||
|
var mileage: Double = 0.0
|
||||||
|
var cost: Double = 0.0
|
||||||
|
var insuranceRenewalDate: LocalDate? = null
|
||||||
|
var pollutionRenewalDate: LocalDate? = null
|
||||||
|
var fitnessRenewalDate: LocalDate? = null
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var renewals: List<FR>? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class FleetType : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: FleetType) {
|
||||||
|
this.name = updated.name
|
||||||
|
this.personIncharge = updated.personIncharge
|
||||||
|
}
|
||||||
|
|
||||||
|
var name: String = ""
|
||||||
|
var personIncharge: String = ""
|
||||||
|
}
|
||||||
|
@Entity
|
||||||
|
open class Renewal : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: Renewal) {
|
||||||
|
this.name = updated.name
|
||||||
|
}
|
||||||
|
|
||||||
|
var name: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class Reminder : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: Reminder) {
|
||||||
|
this.type = updated.type
|
||||||
|
this.nextRenewalDate = updated.nextRenewalDate
|
||||||
|
this.lastRenewalDate = updated.lastRenewalDate
|
||||||
|
this.frequency = updated.frequency
|
||||||
|
this.documents = updated.documents
|
||||||
|
}
|
||||||
|
|
||||||
|
var type: String = "Other"
|
||||||
|
var nextRenewalDate: LocalDate? = null
|
||||||
|
var lastRenewalDate: LocalDate? = null
|
||||||
|
var amount: Double = 0.0
|
||||||
|
var frequency: Int = 1
|
||||||
|
|
||||||
|
@DbArray
|
||||||
|
var documents: List<String>? = arrayListOf()
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
var fleet: Fleet? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class ReminderLog : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: ReminderLog) {
|
||||||
|
this.fleet = updated.fleet
|
||||||
|
this.reminderDate = updated.reminderDate
|
||||||
|
this.reminderType = updated.reminderType
|
||||||
|
this.actedUpon = updated.actedUpon
|
||||||
|
this.documents = updated.documents
|
||||||
|
this.amount = updated.amount
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
var reminder: Reminder? = null
|
||||||
|
var reminderType: String = "Other"
|
||||||
|
var reminderDate: LocalDate? = null
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
var fleet: Fleet? = null
|
||||||
|
var actedUpon: Boolean = false
|
||||||
|
var amount: Double = 0.0
|
||||||
|
|
||||||
|
@DbArray
|
||||||
|
var documents: List<String>? = null
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.restapi.domain
|
||||||
|
|
||||||
|
import io.ebean.annotation.DbJsonB
|
||||||
|
import java.time.LocalDate
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.EnumType
|
||||||
|
import javax.persistence.Enumerated
|
||||||
|
import javax.persistence.ManyToOne
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class IncomingInventory : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: IncomingInventory) {
|
||||||
|
this.date = updated.date
|
||||||
|
this.vendorBillNum = updated.vendorBillNum
|
||||||
|
this.vendorBillAmount = updated.vendorBillAmount
|
||||||
|
this.vehicle = updated.vehicle
|
||||||
|
this.products = updated.products
|
||||||
|
this.vendor = updated.vendor
|
||||||
|
this.loading = updated.loading
|
||||||
|
this.unloading = updated.unloading
|
||||||
|
this.unloadingPlantId = updated.unloadingPlantId
|
||||||
|
}
|
||||||
|
|
||||||
|
var mrn: String? = null
|
||||||
|
var date: LocalDate? = null
|
||||||
|
var vendorBillNum: String? = null
|
||||||
|
var vendorBillAmount: Double = 0.0
|
||||||
|
var vehicle: String = ""
|
||||||
|
var loading: String? = ""
|
||||||
|
var unloadingPlantId: String? = null
|
||||||
|
var unloading: String? = ""
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var products: List<POProducts>? = null
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
var vendor: Vendor? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class OutMode {
|
||||||
|
PERSON, VEHICLE, ALL, JOB, OFFICE
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class OutgoingInventory : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: OutgoingInventory) {
|
||||||
|
this.date = updated.date
|
||||||
|
this.products = updated.products
|
||||||
|
this.purpose = updated.purpose
|
||||||
|
this.outMode = updated.outMode
|
||||||
|
this.person = updated.person
|
||||||
|
this.vehicle = updated.vehicle
|
||||||
|
this.jobCard = updated.jobCard
|
||||||
|
this.unloading = updated.unloading
|
||||||
|
this.unloadingPlantId = updated.unloadingPlantId
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var mdn: String? = null
|
||||||
|
var date: LocalDate? = null
|
||||||
|
var unloadingPlantId: String? = null
|
||||||
|
var unloading: String? = ""
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var products: List<POProducts>? = null
|
||||||
|
var purpose: String? = null
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
var outMode: OutMode? = null
|
||||||
|
|
||||||
|
var person: String? = null
|
||||||
|
|
||||||
|
var jobCard: String? = null
|
||||||
|
|
||||||
|
var vehicle: String? = null
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.restapi.domain
|
||||||
|
|
||||||
|
import javax.persistence.Column
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.EnumType
|
||||||
|
import javax.persistence.Enumerated
|
||||||
|
|
||||||
|
enum class UOM {
|
||||||
|
KG, CFT, TON, LTR, NUMBER, MTR, BOX, CUM, PACKET, ALL, NOS, LITER;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class TypeOfProduct {
|
||||||
|
RAW_MATERIAL
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class Product : BaseTenantModel() {
|
||||||
|
fun patchValues(updatedProduct: Product) {
|
||||||
|
this.name = updatedProduct.name
|
||||||
|
this.description = updatedProduct.description
|
||||||
|
this.hsnCode = updatedProduct.hsnCode
|
||||||
|
this.uom = updatedProduct.uom
|
||||||
|
this.gstPct = updatedProduct.gstPct
|
||||||
|
this.code = updatedProduct.code
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(name = "id")
|
||||||
|
var code: String? = null
|
||||||
|
var name: String = ""
|
||||||
|
var description: String = ""
|
||||||
|
var hsnCode: String = ""
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
var uom: UOM? = null
|
||||||
|
|
||||||
|
var gstPct: Double? = 0.0
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
var type: TypeOfProduct? = null
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
package com.restapi.domain
|
||||||
|
|
||||||
|
import io.ebean.annotation.DbArray
|
||||||
|
import io.ebean.annotation.DbJsonB
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.util.*
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.EnumType
|
||||||
|
import javax.persistence.Enumerated
|
||||||
|
import javax.persistence.ManyToOne
|
||||||
|
|
||||||
|
|
||||||
|
enum class AddressType {
|
||||||
|
BILLING, SHIPPING
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ContactPerson(
|
||||||
|
val id: String = UUID.randomUUID().toString(),
|
||||||
|
val name: String = "", val email: String = "", val mobile: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Address(
|
||||||
|
val id: String = UUID.randomUUID().toString(),
|
||||||
|
val type: AddressType = AddressType.BILLING,
|
||||||
|
val address: String = "",
|
||||||
|
val pincode: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class Vendor : BaseTenantModel() {
|
||||||
|
fun patchValues(updatedVendor: Vendor) {
|
||||||
|
this.name = updatedVendor.name
|
||||||
|
this.msme = updatedVendor.msme
|
||||||
|
this.gstNumber = updatedVendor.gstNumber
|
||||||
|
this.address = updatedVendor.address
|
||||||
|
this.rating = updatedVendor.rating
|
||||||
|
this.contacts = updatedVendor.contacts
|
||||||
|
this.outstanding = updatedVendor.outstanding
|
||||||
|
this.asOnWhichDate = updatedVendor.asOnWhichDate
|
||||||
|
this.addressList = updatedVendor.addressList
|
||||||
|
}
|
||||||
|
|
||||||
|
var name: String = ""
|
||||||
|
var msme: String = ""
|
||||||
|
var gstNumber: String = ""
|
||||||
|
var address: String = ""
|
||||||
|
var rating: Double = 0.0
|
||||||
|
var outstanding: Double? = 0.0
|
||||||
|
var asOnWhichDate: LocalDate? = null
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var addressList: List<Address>? = mutableListOf()
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var contacts: List<ContactPerson> = mutableListOf()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class PurchaseOrder : BaseTenantModel() {
|
||||||
|
fun patchValues(updatedPo: PurchaseOrder) {
|
||||||
|
this.poDate = updatedPo.poDate
|
||||||
|
this.validTill = updatedPo.validTill
|
||||||
|
this.tnc = updatedPo.tnc
|
||||||
|
this.products = updatedPo.products
|
||||||
|
this.vendor = updatedPo.vendor
|
||||||
|
this.documents = updatedPo.documents
|
||||||
|
this.totalAmount = updatedPo.totalAmount
|
||||||
|
this.allLoadingSite = updatedPo.allLoadingSite
|
||||||
|
this.allUnloadingSite = updatedPo.allUnloadingSite
|
||||||
|
this.unloadingPlantId = updatedPo.unloadingPlantId
|
||||||
|
this.loadingSiteId = updatedPo.loadingSiteId
|
||||||
|
}
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var products: MutableList<POProducts> = mutableListOf()
|
||||||
|
@ManyToOne
|
||||||
|
var vendor: Vendor? = null
|
||||||
|
var referenceQuotation: String? = ""
|
||||||
|
var totalAmount: Double = 0.0
|
||||||
|
var poNum: String = ""
|
||||||
|
var poDate: LocalDate? = null
|
||||||
|
var validTill: LocalDate? = null
|
||||||
|
|
||||||
|
var allLoadingSite: Boolean = true
|
||||||
|
var allUnloadingSite: Boolean = true
|
||||||
|
|
||||||
|
var unloadingPlantId: String? = null
|
||||||
|
var loadingSiteId: UUID? = null
|
||||||
|
|
||||||
|
@DbArray
|
||||||
|
var tnc: List<String>? = arrayListOf()
|
||||||
|
|
||||||
|
@DbArray
|
||||||
|
var documents: List<String>? = arrayListOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class Quotation : BaseTenantModel() {
|
||||||
|
fun patchValues(updatedQuote: Quotation) {
|
||||||
|
this.quoteDate = updatedQuote.quoteDate
|
||||||
|
this.vendorQuoteNum = updatedQuote.vendorQuoteNum
|
||||||
|
this.validTill = updatedQuote.validTill
|
||||||
|
this.reqForQuoteNum = updatedQuote.reqForQuoteNum
|
||||||
|
this.tnc = updatedQuote.tnc
|
||||||
|
this.products = updatedQuote.products
|
||||||
|
this.vendor = updatedQuote.vendor
|
||||||
|
this.documents = updatedQuote.documents
|
||||||
|
this.totalAmount = updatedQuote.totalAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var products: MutableList<POProducts> = mutableListOf()
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
var vendor: Vendor? = null
|
||||||
|
var totalAmount: Double = 0.0
|
||||||
|
|
||||||
|
var reqForQuoteNum: String? = ""
|
||||||
|
var quoteNum: String = ""
|
||||||
|
var vendorQuoteNum: String? = ""
|
||||||
|
var quoteDate: LocalDate? = null
|
||||||
|
var validTill: LocalDate? = null
|
||||||
|
|
||||||
|
@DbArray
|
||||||
|
var tnc: List<String>? = arrayListOf()
|
||||||
|
|
||||||
|
@DbArray
|
||||||
|
var documents: List<String>? = arrayListOf()
|
||||||
|
|
||||||
|
var taxesIncluded: Boolean? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class RFQStatus {
|
||||||
|
DELIVERED, PO, QUOTE, CANCELLED
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class ReqForQuote : BaseTenantModel() {
|
||||||
|
@DbArray
|
||||||
|
var potentialVendors: List<Long>? = null
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
var status: RFQStatus? = null
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var products: List<POProducts>? = null
|
||||||
|
var reqForQuoteNum: String? = null
|
||||||
|
var openTill: LocalDate? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class Invoice : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: Invoice) {
|
||||||
|
this.date = updated.date
|
||||||
|
this.number = updated.number
|
||||||
|
this.totalAmount = updated.totalAmount
|
||||||
|
this.poNum = updated.poNum
|
||||||
|
this.products = updated.products
|
||||||
|
this.vendor = updated.vendor
|
||||||
|
this.status = updated.status
|
||||||
|
}
|
||||||
|
|
||||||
|
var number: String = ""
|
||||||
|
var date: LocalDate? = null
|
||||||
|
var totalAmount: Double = 0.0
|
||||||
|
var poNum: String? = null
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var products: List<POProducts>? = null
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
var vendor: Vendor? = null
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
var status: InvoiceStatus? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class Payment : BaseTenantModel() {
|
||||||
|
fun patchValues(updated: Payment) {
|
||||||
|
this.refNumber = updated.refNumber
|
||||||
|
this.amount = updated.amount
|
||||||
|
this.date = updated.date
|
||||||
|
this.remark = updated.remark
|
||||||
|
this.vendor = updated.vendor
|
||||||
|
}
|
||||||
|
|
||||||
|
var refNumber: String = ""
|
||||||
|
var amount: Double = 0.0
|
||||||
|
var date: LocalDate? = null
|
||||||
|
var remark: String? = null
|
||||||
|
var amountDeducted: Double? = null
|
||||||
|
var excessAmount: Double? = null
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var invoicesAffected: MutableMap<Long, Double>? = mutableMapOf()
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
var vendor: Vendor? = null
|
||||||
|
}
|
||||||
@@ -30,7 +30,6 @@ import java.security.spec.PKCS8EncodedKeySpec
|
|||||||
import java.security.spec.X509EncodedKeySpec
|
import java.security.spec.X509EncodedKeySpec
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashMap
|
|
||||||
import kotlin.jvm.optionals.getOrDefault
|
import kotlin.jvm.optionals.getOrDefault
|
||||||
|
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ object Session {
|
|||||||
private val logger = LoggerFactory.getLogger("session")
|
private val logger = LoggerFactory.getLogger("session")
|
||||||
private val currentUser = object : ThreadLocal<AuthUser>() {
|
private val currentUser = object : ThreadLocal<AuthUser>() {
|
||||||
override fun initialValue(): AuthUser {
|
override fun initialValue(): AuthUser {
|
||||||
return AuthUser("", "", emptyList(), "", LocalDateTime.now())
|
return AuthUser("", "", emptyList(), "", LocalDateTime.now(), emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,27 +137,12 @@ object Session {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
fun a(){
|
val objectMapper = jacksonObjectMapper().apply {
|
||||||
val a = HashMap<String,String>()
|
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
a.put("a", "b");
|
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
|
||||||
a.put("a", "b");
|
findAndRegisterModules()
|
||||||
a.put("a", "b");
|
|
||||||
a.put("a", "b");
|
|
||||||
|
|
||||||
val b = HashMap<String,String>().apply {
|
|
||||||
put("a", "b");
|
|
||||||
put("a", "b");
|
|
||||||
put("a", "b");
|
|
||||||
put("a", "b");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val c: String? = ""
|
|
||||||
val x = c?.get(1)
|
|
||||||
|
|
||||||
c?.apply {
|
|
||||||
//will work only when c is not null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private val sc = DatabaseConfig().apply {
|
private val sc = DatabaseConfig().apply {
|
||||||
loadFromProperties(Properties().apply {
|
loadFromProperties(Properties().apply {
|
||||||
setProperty("datasource.db.username", appConfig.dbUser())
|
setProperty("datasource.db.username", appConfig.dbUser())
|
||||||
@@ -169,20 +153,27 @@ object Session {
|
|||||||
tenantMode = TenantMode.PARTITION
|
tenantMode = TenantMode.PARTITION
|
||||||
currentTenantProvider = CurrentTenantProvider { currentUser.get().tenant }
|
currentTenantProvider = CurrentTenantProvider { currentUser.get().tenant }
|
||||||
currentUserProvider = CurrentUserProvider { currentUser.get().userName }
|
currentUserProvider = CurrentUserProvider { currentUser.get().userName }
|
||||||
|
objectMapper = Session.objectMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
val database: Database = DatabaseFactory.create(sc)
|
val database: Database = DatabaseFactory.create(sc)
|
||||||
val objectMapper = jacksonObjectMapper().apply {
|
|
||||||
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
|
||||||
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
|
|
||||||
findAndRegisterModules()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun currentUser() = currentUser.get().userName
|
fun currentUser() = currentUser.get().userName
|
||||||
fun currentTenant() = currentUser.get().tenant
|
fun currentTenant() = currentUser.get().tenant
|
||||||
fun currentRoles() = currentUser.get().roles
|
fun currentRoles() = currentUser.get().roles
|
||||||
fun currentToken() = currentUser.get().token
|
fun currentUserPlants() = currentUser.get().plantIds.mapNotNull {
|
||||||
fun jwk() = keypair.toParams(JsonWebKey.OutputControlLevel.PUBLIC_ONLY)
|
database.find(Plant::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("plantId", it)
|
||||||
|
.findOne()
|
||||||
|
?.apply {
|
||||||
|
if (this.prefixes == null || this.prefixes.isNullOrEmpty()) {
|
||||||
|
this.prefixes = mutableMapOf("INBOUND" to "MRN/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun jwk(): MutableMap<String, Any> = keypair.toParams(JsonWebKey.OutputControlLevel.PUBLIC_ONLY)
|
||||||
|
|
||||||
fun Database.findDataModelByEntityAndUniqId(entity: String, uniqId: String): DataModel {
|
fun Database.findDataModelByEntityAndUniqId(entity: String, uniqId: String): DataModel {
|
||||||
return find(DataModel::class.java)
|
return find(DataModel::class.java)
|
||||||
@@ -192,7 +183,8 @@ object Session {
|
|||||||
.findOne() ?: throw DataNotFoundException
|
.findOne() ?: throw DataNotFoundException
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun seqName(entity: String) = "sequence_$entity"
|
private fun seqName(entity: String) = "sequence_${entity}_${currentTenant()}"
|
||||||
|
|
||||||
fun creatSeq(entity: String): Int {
|
fun creatSeq(entity: String): Int {
|
||||||
return database.sqlUpdate("CREATE SEQUENCE IF NOT EXISTS ${seqName(entity)} START 1;").execute()
|
return database.sqlUpdate("CREATE SEQUENCE IF NOT EXISTS ${seqName(entity)} START 1;").execute()
|
||||||
}
|
}
|
||||||
@@ -201,11 +193,9 @@ object Session {
|
|||||||
val s = database
|
val s = database
|
||||||
.sqlQuery("SELECT nextval('${seqName(entity)}');")
|
.sqlQuery("SELECT nextval('${seqName(entity)}');")
|
||||||
.findOne()?.getLong("nextval") ?: throw DataNotFoundException
|
.findOne()?.getLong("nextval") ?: throw DataNotFoundException
|
||||||
return "$entity-${"$s".padStart(10, '0')}"
|
return "$entity-${"$s".padStart(6, '0')}"
|
||||||
}
|
}
|
||||||
|
|
||||||
val redis = JedisPooled(appConfig.redisUri().getOrDefault("redis://localhost:6739/0"))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object DataNotFoundException : Exception() {
|
object DataNotFoundException : Exception() {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ object DBMigration {
|
|||||||
private fun create(){
|
private fun create(){
|
||||||
val dbMigration: DbMigration = DbMigration.create()
|
val dbMigration: DbMigration = DbMigration.create()
|
||||||
dbMigration.setPlatform(Platform.POSTGRES)
|
dbMigration.setPlatform(Platform.POSTGRES)
|
||||||
|
//dbMigration.setGeneratePendingDrop("1.8")
|
||||||
dbMigration.generateMigration()
|
dbMigration.generateMigration()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,29 @@ import io.ebean.annotation.*
|
|||||||
import io.ebean.annotation.Index
|
import io.ebean.annotation.Index
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.*
|
|
||||||
import javax.persistence.*
|
import javax.persistence.*
|
||||||
|
|
||||||
data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now())
|
data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now())
|
||||||
data class POProducts(val productId: String = "", val unitPrice :Double = 0.0, val quantity: Double = 0.0, val description :String = "")
|
data class ReceivedVoucher(val ticket: String, val productName: String, val productId: Long, val qty: Double, val plantId: String = "", val ticketDate: LocalDate = LocalDate.now())
|
||||||
|
data class POProducts(
|
||||||
|
val productId: Long = 0,
|
||||||
|
val productName: String = "",
|
||||||
|
val unitPrice: Double = 0.0,
|
||||||
|
val quantity: Double = 0.0,
|
||||||
|
val orderedQty: Double = 0.0,
|
||||||
|
val receivedQty: Double = 0.0,
|
||||||
|
val receivedVoucher: MutableList<ReceivedVoucher> = arrayListOf(),
|
||||||
|
val billQty: Double = 0.0,
|
||||||
|
val gstPct: Double = 0.0,
|
||||||
|
val taxableValue: Double = 0.0,
|
||||||
|
val totalValue: Double = 0.0,
|
||||||
|
val description: String = "",
|
||||||
|
val uom: String = "",
|
||||||
|
val poId: Long? = null,
|
||||||
|
val isAvailable: Boolean? = false
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
enum class ApprovalStatus {
|
enum class ApprovalStatus {
|
||||||
PENDING, APPROVED, REJECTED
|
PENDING, APPROVED, REJECTED
|
||||||
}
|
}
|
||||||
@@ -104,15 +122,13 @@ open class AuditLog : BaseTenantModel() {
|
|||||||
|
|
||||||
@DbJsonB
|
@DbJsonB
|
||||||
@Index(
|
@Index(
|
||||||
definition = "create index audit_log_values_idx on audit_log using GIN (data)",
|
definition = "create index audit_log_values_idx on audit_log using GIN (data)", platforms = [Platform.POSTGRES]
|
||||||
platforms = [Platform.POSTGRES]
|
|
||||||
)
|
)
|
||||||
var data: Map<String, Any> = hashMapOf()
|
var data: Map<String, Any> = hashMapOf()
|
||||||
|
|
||||||
@DbJsonB
|
@DbJsonB
|
||||||
@Index(
|
@Index(
|
||||||
definition = "create index audit_log_changes_idx on audit_log using GIN (changes)",
|
definition = "create index audit_log_changes_idx on audit_log using GIN (changes)", platforms = [Platform.POSTGRES]
|
||||||
platforms = [Platform.POSTGRES]
|
|
||||||
)
|
)
|
||||||
var changes: Map<String, Any> = hashMapOf()
|
var changes: Map<String, Any> = hashMapOf()
|
||||||
}
|
}
|
||||||
@@ -168,18 +184,6 @@ enum class JobType {
|
|||||||
SCRIPT, DB
|
SCRIPT, DB
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Index(unique = true, name = "sql_unique_id", columnNames = ["entity_name", "sql_id", "tenant_id"])
|
|
||||||
open class SqlModel : BaseTenantModel() {
|
|
||||||
|
|
||||||
@JsonDeserialize(using = SafeStringDeserializer::class)
|
|
||||||
var sqlId: String = ""
|
|
||||||
|
|
||||||
var entityName: String = ""
|
|
||||||
|
|
||||||
@Column(columnDefinition = "text")
|
|
||||||
var sql: String = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
open class JobModel : BaseTenantModel() {
|
open class JobModel : BaseTenantModel() {
|
||||||
@@ -217,7 +221,6 @@ open class DataModel : BaseTenantModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Index(unique = true, name = "unique_session_id", columnNames = ["session_id"])
|
@Index(unique = true, name = "unique_session_id", columnNames = ["session_id"])
|
||||||
open class AnonSession : BaseTenantModel() {
|
open class AnonSession : BaseTenantModel() {
|
||||||
@@ -232,103 +235,88 @@ open class AnonSession : BaseTenantModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SafeStringDeserializer : JsonDeserializer<String>() {
|
class SafeStringDeserializer : JsonDeserializer<String>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
|
private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
|
||||||
|
|
||||||
|
fun isSafe(s: String) = regex.matches(s)
|
||||||
|
}
|
||||||
|
|
||||||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): String {
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): String {
|
||||||
|
|
||||||
val text = p.text
|
val text = p.text
|
||||||
if (!regex.matches(text)) throw IllegalArgumentException()
|
if (!isSafe(text)) throw IllegalArgumentException()
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ContactPerson(val name: String, val email: String, val mobile: String)
|
|
||||||
@Entity
|
|
||||||
open class Vendor :BaseTenantModel() {
|
|
||||||
var name :String = ""
|
|
||||||
var msme :String = ""
|
|
||||||
var gstNumber :String = ""
|
|
||||||
var address :String = ""
|
|
||||||
var rating :Double = 0.0
|
|
||||||
@DbJsonB
|
|
||||||
var contacts :List<ContactPerson> = mutableListOf()
|
|
||||||
}
|
|
||||||
@Entity
|
|
||||||
open class PurchaseOrder :BaseTenantModel() {
|
|
||||||
@DbJsonB
|
|
||||||
var products :MutableList<POProducts> = mutableListOf()
|
|
||||||
@ManyToOne
|
|
||||||
var vendor :Vendor? = null
|
|
||||||
var referenceQuotation :String = ""
|
|
||||||
var totalAmount :Int = 0
|
|
||||||
var poNum: String = ""
|
|
||||||
var poDate: LocalDate? = null
|
|
||||||
var validTill: LocalDate? = null
|
|
||||||
@DbArray
|
|
||||||
var tnc: List<String> = arrayListOf()
|
|
||||||
@DbArray
|
|
||||||
var documents: MutableList<Long> = arrayListOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class UOM {
|
enum class DocType {
|
||||||
NOS, LTR, MTR, ALL
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
open class Product :BaseTenantModel() {
|
|
||||||
var id: Int? = null
|
|
||||||
var name :String = ""
|
|
||||||
var description :String = ""
|
|
||||||
var hsnCode :String = ""
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
var uom: UOM? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
open class Quotation :BaseTenantModel() {
|
|
||||||
@DbJsonB
|
|
||||||
var products :MutableList<POProducts> = mutableListOf()
|
|
||||||
@ManyToOne
|
|
||||||
var vendor :Vendor? = null
|
|
||||||
var totalAmount :Long = 0
|
|
||||||
|
|
||||||
var reqForQuoteNum: String = ""
|
|
||||||
var quoteNum: String = ""
|
|
||||||
var quoteDate: LocalDate? = null
|
|
||||||
var validTill: LocalDate? = null
|
|
||||||
@DbArray
|
|
||||||
var tnc: List<String> = arrayListOf()
|
|
||||||
|
|
||||||
@DbArray
|
|
||||||
var documents: MutableList<Long> = arrayListOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class DocType{
|
|
||||||
PO, QUOTE, INVOICE, ALL
|
PO, QUOTE, INVOICE, ALL
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
open class Document :BaseTenantModel() {
|
open class Document : BaseTenantModel() {
|
||||||
var name :String = ""
|
var name: String = ""
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
var typeOfDoc :DocType? = null
|
var typeOfDoc: DocType? = null
|
||||||
var refId: Long? = null
|
|
||||||
var description :String = ""
|
//could be quoteNum, PoNum, InvoiceNum
|
||||||
var url :String = ""
|
var refIdOfDoc: Long? = null
|
||||||
|
var description: String = ""
|
||||||
|
var url: String = ""
|
||||||
|
var docDate: LocalDate? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class RFQStatus{
|
|
||||||
DELIVERED, PO, QUOTE, CANCELLED
|
enum class InvoiceStatus {
|
||||||
|
PAID_FULL, PAID_SOME, PAID_NONE, ALL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
open class ReqForQuote :BaseTenantModel() {
|
@Index(name = "plantid_idx", columnNames = ["plant_id"], unique = true)
|
||||||
@DbArray
|
open class Plant : BaseModel() {
|
||||||
var potentialVendors :List<Long>? = null
|
fun patch(p: Plant) {
|
||||||
@Enumerated(EnumType.STRING)
|
this.plantName = p.plantName
|
||||||
var status :RFQStatus? = null
|
this.prefixes?.apply {
|
||||||
@DbArray
|
this.clear()
|
||||||
var docs :List<Document>? = null
|
this.putAll(p.prefixes ?: emptyMap())
|
||||||
|
}
|
||||||
|
this.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
var plantId: String = ""
|
||||||
|
var plantName: String = ""
|
||||||
|
var plantOriginalName: String? = ""
|
||||||
|
|
||||||
@DbJsonB
|
@DbJsonB
|
||||||
var products :List<POProducts>? = null
|
var prefixes: MutableMap<String, String>? = mutableMapOf()
|
||||||
var reqForQuoteNum: String = ""
|
}
|
||||||
var openTill: LocalDate? = null
|
|
||||||
|
class RefreshHistory {
|
||||||
|
var oldAt: String = ""
|
||||||
|
var oldExpiryAt: String = ""
|
||||||
|
var newAt: String = ""
|
||||||
|
var newExpiryAt: String = ""
|
||||||
|
var createdAt: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
open class AuthTokenCache : BaseModel() {
|
||||||
|
@Column(columnDefinition = "text")
|
||||||
|
var authToken: String = ""
|
||||||
|
var issuedAt: LocalDateTime = LocalDateTime.now()
|
||||||
|
var expiresAt: LocalDateTime = LocalDateTime.now()
|
||||||
|
var refreshExpiresAt: LocalDateTime = LocalDateTime.now()
|
||||||
|
|
||||||
|
@Column(columnDefinition = "text")
|
||||||
|
var refreshToken: String = ""
|
||||||
|
var userId: String = ""
|
||||||
|
var expired: Boolean = false
|
||||||
|
var loggedOut: Boolean = false
|
||||||
|
|
||||||
|
@DbJsonB
|
||||||
|
var refreshHistory: MutableList<RefreshHistory>? = arrayListOf()
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table incoming_inventory drop column vendor_bil_num;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table incoming_inventory drop column mdn;
|
||||||
|
alter table outgoing_inventory drop column mrn;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
-- apply changes
|
||||||
|
create table invoice (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
date date,
|
||||||
|
total_amount float not null,
|
||||||
|
vendor_sys_pk bigint,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
number varchar(255) not null,
|
||||||
|
po_num varchar(255),
|
||||||
|
products jsonb,
|
||||||
|
status varchar(9),
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_invoice_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint ck_invoice_status check ( status in ('PAID_FULL','PAID_SOME','PAID_NONE','ALL')),
|
||||||
|
constraint pk_invoice primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table payment (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
amount float not null,
|
||||||
|
date date,
|
||||||
|
vendor_sys_pk bigint,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
ref_number varchar(255) not null,
|
||||||
|
remark varchar(255),
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_payment_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_payment primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- apply alter tables
|
||||||
|
alter table vendor add column if not exists outstanding float;
|
||||||
|
alter table vendor add column if not exists as_on_which_date date;
|
||||||
|
-- foreign keys and indices
|
||||||
|
create index ix_invoice_vendor_sys_pk on invoice (vendor_sys_pk);
|
||||||
|
alter table invoice add constraint fk_invoice_vendor_sys_pk foreign key (vendor_sys_pk) references vendor (sys_pk) on delete restrict on update restrict;
|
||||||
|
|
||||||
|
create index ix_payment_vendor_sys_pk on payment (vendor_sys_pk);
|
||||||
|
alter table payment add constraint fk_payment_vendor_sys_pk foreign key (vendor_sys_pk) references vendor (sys_pk) on delete restrict on update restrict;
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table payment add column if not exists excess_amount float;
|
||||||
|
alter table payment add column if not exists invoices_affected jsonb;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table payment add column if not exists amount_deducted float;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
-- apply changes
|
||||||
|
create table fleet (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
mileage float not null,
|
||||||
|
cost float not null,
|
||||||
|
insurance_renewal_date date,
|
||||||
|
pollution_renewal_date date,
|
||||||
|
fitness_renewal_date date,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
name varchar(255) not null,
|
||||||
|
type varchar(255) not null,
|
||||||
|
reg_number varchar(255) not null,
|
||||||
|
model varchar(255) not null,
|
||||||
|
make varchar(255) not null,
|
||||||
|
driver varchar(255) not null,
|
||||||
|
driver_contact varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_fleet_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_fleet primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
-- apply changes
|
||||||
|
create table fleet_type (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
name varchar(255) not null,
|
||||||
|
person_incharge varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_fleet_type_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_fleet_type primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table renewal (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
name varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_renewal_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_renewal primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table vehicle (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
name varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_vehicle_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_vehicle primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- apply alter tables
|
||||||
|
alter table fleet add column if not exists renewals jsonb;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
-- apply changes
|
||||||
|
create table fleet_renewal (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
date date,
|
||||||
|
last_date date,
|
||||||
|
frequency integer not null,
|
||||||
|
fleet_sys_pk bigint,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
name varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_fleet_renewal_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_fleet_renewal primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- foreign keys and indices
|
||||||
|
create index ix_fleet_renewal_fleet_sys_pk on fleet_renewal (fleet_sys_pk);
|
||||||
|
alter table fleet_renewal add constraint fk_fleet_renewal_fleet_sys_pk foreign key (fleet_sys_pk) references fleet (sys_pk) on delete restrict on update restrict;
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table fleet_renewal add column if not exists documents varchar[];
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
-- drop dependencies
|
||||||
|
alter table if exists fleet_renewal drop constraint if exists fk_fleet_renewal_fleet_sys_pk;
|
||||||
|
-- apply changes
|
||||||
|
create table reminder (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
next_renewal_date date,
|
||||||
|
last_renewal_date date,
|
||||||
|
amount float not null,
|
||||||
|
frequency integer not null,
|
||||||
|
fleet_sys_pk bigint,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
type varchar(255) not null,
|
||||||
|
documents varchar[],
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_reminder_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_reminder primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table reminder_log (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
reminder_date date,
|
||||||
|
fleet_sys_pk bigint,
|
||||||
|
acted_upon boolean default false not null,
|
||||||
|
amount float not null,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
reminder_type varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_reminder_log_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_reminder_log primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- foreign keys and indices
|
||||||
|
create index ix_reminder_fleet_sys_pk on reminder (fleet_sys_pk);
|
||||||
|
alter table reminder add constraint fk_reminder_fleet_sys_pk foreign key (fleet_sys_pk) references fleet (sys_pk) on delete restrict on update restrict;
|
||||||
|
|
||||||
|
create index ix_reminder_log_fleet_sys_pk on reminder_log (fleet_sys_pk);
|
||||||
|
alter table reminder_log add constraint fk_reminder_log_fleet_sys_pk foreign key (fleet_sys_pk) references fleet (sys_pk) on delete restrict on update restrict;
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table reminder_log add column if not exists documents varchar[];
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table reminder_log add column if not exists reminder_sys_pk bigint;
|
||||||
|
-- foreign keys and indices
|
||||||
|
create index ix_reminder_log_reminder_sys_pk on reminder_log (reminder_sys_pk);
|
||||||
|
alter table reminder_log add constraint fk_reminder_log_reminder_sys_pk foreign key (reminder_sys_pk) references reminder (sys_pk) on delete restrict on update restrict;
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table fleet add column if not exists reg_date date;
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
-- apply changes
|
||||||
|
create table plant (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
plant_id varchar(255) not null,
|
||||||
|
plant_name varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_plant_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint plantid_idx unique (plant_id),
|
||||||
|
constraint pk_plant primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table product alter column id type varchar(255) using id::varchar(255);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table incoming_inventory add column if not exists loading varchar(255);
|
||||||
|
alter table incoming_inventory add column if not exists unloading varchar(255);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
-- drop dependencies
|
||||||
|
alter table product drop constraint if exists ck_product_uom;
|
||||||
|
-- apply alter tables
|
||||||
|
alter table product alter column uom type varchar(6);
|
||||||
|
alter table product add column if not exists gst_pct float;
|
||||||
|
-- apply post alter
|
||||||
|
alter table product add constraint ck_product_uom check ( uom in ('KG','CFT','TON','LTR','NUMBER','MTR','BOX','CUM','PACKET','ALL','NOS'));
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table vendor add column if not exists address_list jsonb;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table incoming_inventory add column if not exists unloading_plant_id varchar(255);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table plant add column if not exists prefixes jsonb;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
-- drop dependencies
|
||||||
|
alter table document drop constraint if exists ck_document_type_of_doc;
|
||||||
|
alter table product drop constraint if exists ck_product_uom;
|
||||||
|
-- apply changes
|
||||||
|
create table req_for_quote (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
potential_vendors bigint[],
|
||||||
|
open_till date,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
status varchar(9),
|
||||||
|
products jsonb,
|
||||||
|
req_for_quote_num varchar(255),
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_req_for_quote_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint ck_req_for_quote_status check ( status in ('DELIVERED','PO','QUOTE','CANCELLED')),
|
||||||
|
constraint pk_req_for_quote primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- apply alter tables
|
||||||
|
alter table document alter column type_of_doc type varchar(7) using type_of_doc::varchar(7);
|
||||||
|
alter table document alter column type_of_doc drop not null;
|
||||||
|
alter table document add column if not exists ref_id varchar(255);
|
||||||
|
alter table document add column if not exists doc_date date;
|
||||||
|
alter table product add column if not exists id bigint;
|
||||||
|
alter table purchase_order alter column reference_quotation drop not null;
|
||||||
|
alter table purchase_order alter column total_amount type float using total_amount::float;
|
||||||
|
alter table quotation alter column total_amount type float using total_amount::float;
|
||||||
|
alter table quotation add column if not exists req_for_quote_num varchar(255);
|
||||||
|
-- apply post alter
|
||||||
|
alter table document add constraint ck_document_type_of_doc check ( type_of_doc in ('PO','QUOTE','INVOICE','ALL'));
|
||||||
|
alter table product add constraint ck_product_uom check ( uom in ('NOS','LTR','MTR','ALL'));
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
-- apply changes
|
||||||
|
create table auth_token_cache (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
auth_token text not null,
|
||||||
|
issued_at timestamp not null,
|
||||||
|
expires_at timestamp not null,
|
||||||
|
refresh_expires_at timestamp not null,
|
||||||
|
refresh_token text not null,
|
||||||
|
expired boolean default false not null,
|
||||||
|
logged_out boolean default false not null,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
user_id varchar(255) not null,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_auth_token_cache_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_auth_token_cache primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table auth_token_cache add column if not exists refresh_history jsonb;
|
||||||
|
alter table product add column if not exists id varchar(255);
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table outgoing_inventory add column if not exists unloading_plant_id varchar(255);
|
||||||
|
alter table outgoing_inventory add column if not exists unloading varchar(255);
|
||||||
|
alter table outgoing_inventory add column if not exists job_card varchar(255);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table purchase_order add column if not exists all_loading_site boolean default true not null;
|
||||||
|
alter table purchase_order add column if not exists all_unloading_site boolean default true not null;
|
||||||
|
alter table purchase_order add column if not exists unloading_plant_id varchar(255);
|
||||||
|
alter table purchase_order add column if not exists loading_site_id uuid;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
-- drop dependencies
|
||||||
|
alter table product drop constraint if exists ck_product_uom;
|
||||||
|
-- apply alter tables
|
||||||
|
alter table purchase_order alter column all_loading_site set default false;
|
||||||
|
alter table purchase_order alter column all_unloading_site set default false;
|
||||||
|
-- apply post alter
|
||||||
|
alter table product add constraint ck_product_uom check ( uom in ('KG','CFT','TON','LTR','NUMBER','MTR','BOX','CUM','PACKET','ALL','NOS','LITER'));
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- drop dependencies
|
||||||
|
alter table outgoing_inventory drop constraint if exists ck_outgoing_inventory_out_mode;
|
||||||
|
-- apply post alter
|
||||||
|
alter table outgoing_inventory add constraint ck_outgoing_inventory_out_mode check ( out_mode in ('PERSON','VEHICLE','ALL','JOB','OFFICE'));
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table plant add column if not exists plant_original_name varchar(255);
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table purchase_order alter column tnc drop not null;
|
||||||
|
alter table purchase_order alter column documents type varchar[] using documents::varchar[];
|
||||||
|
alter table purchase_order alter column documents drop not null;
|
||||||
|
alter table quotation alter column tnc drop not null;
|
||||||
|
alter table quotation alter column documents type varchar[] using documents::varchar[];
|
||||||
|
alter table quotation alter column documents drop not null;
|
||||||
|
alter table quotation add column if not exists vendor_quote_num varchar(255);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table document add column if not exists ref_id_of_doc bigint;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
-- apply changes
|
||||||
|
create table incoming_inventory (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
date date,
|
||||||
|
vendor_bill_amount float not null,
|
||||||
|
vendor_sys_pk bigint,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
mdn varchar(255) not null,
|
||||||
|
vendor_bil_num varchar(255) not null,
|
||||||
|
vehicle varchar(255) not null,
|
||||||
|
products jsonb,
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_incoming_inventory_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint pk_incoming_inventory primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table outgoing_inventory (
|
||||||
|
sys_pk bigint generated by default as identity not null,
|
||||||
|
deleted_on timestamp,
|
||||||
|
current_approval_level integer default 0 not null,
|
||||||
|
required_approval_levels integer default 0 not null,
|
||||||
|
date date,
|
||||||
|
deleted boolean default false not null,
|
||||||
|
version integer default 1 not null,
|
||||||
|
created_at timestamp default 'now()' not null,
|
||||||
|
modified_at timestamp default 'now()' not null,
|
||||||
|
deleted_by varchar(255),
|
||||||
|
approval_status varchar(8) default 'APPROVED' not null,
|
||||||
|
tags varchar[] default '{}' not null,
|
||||||
|
comments jsonb default '[]' not null,
|
||||||
|
tenant_id varchar(255) not null,
|
||||||
|
mrn varchar(255) not null,
|
||||||
|
purpose varchar(255),
|
||||||
|
out_mode varchar(7),
|
||||||
|
person varchar(255),
|
||||||
|
vehicle varchar(255),
|
||||||
|
created_by varchar(255) not null,
|
||||||
|
modified_by varchar(255) not null,
|
||||||
|
constraint ck_outgoing_inventory_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||||
|
constraint ck_outgoing_inventory_out_mode check ( out_mode in ('PERSON','VEHICLE','ALL')),
|
||||||
|
constraint pk_outgoing_inventory primary key (sys_pk)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- apply alter tables
|
||||||
|
alter table product add column if not exists type varchar(12);
|
||||||
|
alter table quotation add column if not exists taxes_included boolean;
|
||||||
|
-- apply post alter
|
||||||
|
alter table product add constraint ck_product_type check ( type in ('RAW_MATERIAL'));
|
||||||
|
-- foreign keys and indices
|
||||||
|
create index ix_incoming_inventory_vendor_sys_pk on incoming_inventory (vendor_sys_pk);
|
||||||
|
alter table incoming_inventory add constraint fk_incoming_inventory_vendor_sys_pk foreign key (vendor_sys_pk) references vendor (sys_pk) on delete restrict on update restrict;
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table incoming_inventory add column if not exists vendor_bill_num varchar(255);
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table incoming_inventory add column if not exists mrn varchar(255);
|
||||||
|
alter table outgoing_inventory add column if not exists mdn varchar(255);
|
||||||
|
alter table outgoing_inventory add column if not exists products jsonb;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- apply alter tables
|
||||||
|
alter table document drop column ref_id;
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply" dropsFor="1.7">
|
||||||
|
<dropColumn columnName="vendor_bil_num" tableName="incoming_inventory"/>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply" dropsFor="1.8">
|
||||||
|
<dropColumn columnName="mdn" tableName="incoming_inventory"/>
|
||||||
|
<dropColumn columnName="mrn" tableName="outgoing_inventory"/>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<createTable name="invoice" pkName="pk_invoice">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_invoice_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="number" type="varchar" notnull="true"/>
|
||||||
|
<column name="date" type="date"/>
|
||||||
|
<column name="total_amount" type="double" notnull="true"/>
|
||||||
|
<column name="po_num" type="varchar"/>
|
||||||
|
<column name="products" type="jsonb"/>
|
||||||
|
<column name="vendor_sys_pk" type="bigint" references="vendor.sys_pk" foreignKeyName="fk_invoice_vendor_sys_pk" foreignKeyIndex="ix_invoice_vendor_sys_pk"/>
|
||||||
|
<column name="status" type="varchar(9)" checkConstraint="check ( status in ('PAID_FULL','PAID_SOME','PAID_NONE','ALL'))" checkConstraintName="ck_invoice_status"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable name="payment" pkName="pk_payment">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_payment_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="ref_number" type="varchar" notnull="true"/>
|
||||||
|
<column name="amount" type="double" notnull="true"/>
|
||||||
|
<column name="date" type="date"/>
|
||||||
|
<column name="remark" type="varchar"/>
|
||||||
|
<column name="vendor_sys_pk" type="bigint" references="vendor.sys_pk" foreignKeyName="fk_payment_vendor_sys_pk" foreignKeyIndex="ix_payment_vendor_sys_pk"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
<addColumn tableName="vendor">
|
||||||
|
<column name="outstanding" type="double"/>
|
||||||
|
<column name="as_on_which_date" type="date"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="payment">
|
||||||
|
<column name="excess_amount" type="double"/>
|
||||||
|
<column name="invoices_affected" type="jsonb"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="payment">
|
||||||
|
<column name="amount_deducted" type="double"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<createTable name="fleet" pkName="pk_fleet">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_fleet_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="name" type="varchar" notnull="true"/>
|
||||||
|
<column name="type" type="varchar" notnull="true"/>
|
||||||
|
<column name="reg_number" type="varchar" notnull="true"/>
|
||||||
|
<column name="model" type="varchar" notnull="true"/>
|
||||||
|
<column name="make" type="varchar" notnull="true"/>
|
||||||
|
<column name="driver" type="varchar" notnull="true"/>
|
||||||
|
<column name="driver_contact" type="varchar" notnull="true"/>
|
||||||
|
<column name="mileage" type="double" notnull="true"/>
|
||||||
|
<column name="cost" type="double" notnull="true"/>
|
||||||
|
<column name="insurance_renewal_date" type="date"/>
|
||||||
|
<column name="pollution_renewal_date" type="date"/>
|
||||||
|
<column name="fitness_renewal_date" type="date"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="fleet">
|
||||||
|
<column name="renewals" type="jsonb"/>
|
||||||
|
</addColumn>
|
||||||
|
<createTable name="fleet_type" pkName="pk_fleet_type">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_fleet_type_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="name" type="varchar" notnull="true"/>
|
||||||
|
<column name="person_incharge" type="varchar" notnull="true"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable name="renewal" pkName="pk_renewal">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_renewal_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="name" type="varchar" notnull="true"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable name="vehicle" pkName="pk_vehicle">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_vehicle_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="name" type="varchar" notnull="true"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<createTable name="fleet_renewal" pkName="pk_fleet_renewal">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_fleet_renewal_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="name" type="varchar" notnull="true"/>
|
||||||
|
<column name="date" type="date"/>
|
||||||
|
<column name="last_date" type="date"/>
|
||||||
|
<column name="frequency" type="integer" notnull="true"/>
|
||||||
|
<column name="fleet_sys_pk" type="bigint" references="fleet.sys_pk" foreignKeyName="fk_fleet_renewal_fleet_sys_pk" foreignKeyIndex="ix_fleet_renewal_fleet_sys_pk"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="fleet_renewal">
|
||||||
|
<column name="documents" type="varchar[]"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<createTable name="reminder" pkName="pk_reminder">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_reminder_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="type" type="varchar" notnull="true"/>
|
||||||
|
<column name="next_renewal_date" type="date"/>
|
||||||
|
<column name="last_renewal_date" type="date"/>
|
||||||
|
<column name="amount" type="double" notnull="true"/>
|
||||||
|
<column name="frequency" type="integer" notnull="true"/>
|
||||||
|
<column name="documents" type="varchar[]"/>
|
||||||
|
<column name="fleet_sys_pk" type="bigint" references="fleet.sys_pk" foreignKeyName="fk_reminder_fleet_sys_pk" foreignKeyIndex="ix_reminder_fleet_sys_pk"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable name="reminder_log" pkName="pk_reminder_log">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_reminder_log_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="reminder_type" type="varchar" notnull="true"/>
|
||||||
|
<column name="reminder_date" type="date"/>
|
||||||
|
<column name="fleet_sys_pk" type="bigint" references="fleet.sys_pk" foreignKeyName="fk_reminder_log_fleet_sys_pk" foreignKeyIndex="ix_reminder_log_fleet_sys_pk"/>
|
||||||
|
<column name="acted_upon" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="amount" type="double" notnull="true"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
<alterForeignKey name="fk_fleet_renewal_fleet_sys_pk" columnNames="DROP FOREIGN KEY" indexName="ix_fleet_renewal_fleet_sys_pk" tableName="fleet_renewal"/>
|
||||||
|
</changeSet>
|
||||||
|
<changeSet type="pendingDrops">
|
||||||
|
<dropTable name="fleet_renewal" sequenceCol="sys_pk"/>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="reminder_log">
|
||||||
|
<column name="documents" type="varchar[]"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="reminder_log">
|
||||||
|
<column name="reminder_sys_pk" type="bigint" references="reminder.sys_pk" foreignKeyName="fk_reminder_log_reminder_sys_pk" foreignKeyIndex="ix_reminder_log_reminder_sys_pk"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="fleet">
|
||||||
|
<column name="reg_date" type="date"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<createTable name="plant" pkName="pk_plant">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_plant_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="plant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="plant_name" type="varchar" notnull="true"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
<uniqueConstraint name="plantid_idx" columnNames="plant_id" oneToOne="false" nullableColumns=""/>
|
||||||
|
</createTable>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<alterColumn columnName="code" tableName="product" type="varchar" currentType="bigint" currentNotnull="false"/>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="incoming_inventory">
|
||||||
|
<column name="loading" type="varchar"/>
|
||||||
|
<column name="unloading" type="varchar"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<alterColumn columnName="uom" tableName="product" type="varchar(6)" currentType="varchar(3)" currentNotnull="false" checkConstraint="check ( uom in ('KG','CFT','TON','LTR','NUMBER','MTR','BOX','CUM','PACKET','ALL','NOS'))" checkConstraintName="ck_product_uom"/>
|
||||||
|
<addColumn tableName="product">
|
||||||
|
<column name="gst_pct" type="double"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="vendor">
|
||||||
|
<column name="address_list" type="jsonb"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="incoming_inventory">
|
||||||
|
<column name="unloading_plant_id" type="varchar"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="plant">
|
||||||
|
<column name="prefixes" type="jsonb"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<alterColumn columnName="type_of_doc" tableName="document" type="varchar(7)" currentType="varchar" notnull="false" currentNotnull="true" checkConstraint="check ( type_of_doc in ('PO','QUOTE','INVOICE','ALL'))" checkConstraintName="ck_document_type_of_doc"/>
|
||||||
|
<addColumn tableName="document">
|
||||||
|
<column name="ref_id" type="varchar"/>
|
||||||
|
<column name="doc_date" type="date"/>
|
||||||
|
</addColumn>
|
||||||
|
<alterColumn columnName="uom" tableName="product" checkConstraint="check ( uom in ('NOS','LTR','MTR','ALL'))" checkConstraintName="ck_product_uom"/>
|
||||||
|
<addColumn tableName="product">
|
||||||
|
<column name="code" type="bigint"/>
|
||||||
|
</addColumn>
|
||||||
|
<alterColumn columnName="reference_quotation" tableName="purchase_order" currentType="varchar" notnull="false" currentNotnull="true"/>
|
||||||
|
<alterColumn columnName="total_amount" tableName="purchase_order" type="double" currentType="integer" currentNotnull="true"/>
|
||||||
|
<alterColumn columnName="total_amount" tableName="quotation" type="double" currentType="integer" currentNotnull="true"/>
|
||||||
|
<addColumn tableName="quotation">
|
||||||
|
<column name="req_for_quote_num" type="varchar"/>
|
||||||
|
</addColumn>
|
||||||
|
<createTable name="req_for_quote" pkName="pk_req_for_quote">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_req_for_quote_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="potential_vendors" type="bigint[]"/>
|
||||||
|
<column name="status" type="varchar(9)" checkConstraint="check ( status in ('DELIVERED','PO','QUOTE','CANCELLED'))" checkConstraintName="ck_req_for_quote_status"/>
|
||||||
|
<column name="products" type="jsonb"/>
|
||||||
|
<column name="req_for_quote_num" type="varchar"/>
|
||||||
|
<column name="open_till" type="date"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<createTable name="auth_token_cache" pkName="pk_auth_token_cache">
|
||||||
|
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||||
|
<column name="deleted_on" type="localdatetime"/>
|
||||||
|
<column name="deleted_by" type="varchar"/>
|
||||||
|
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||||
|
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_auth_token_cache_approval_status"/>
|
||||||
|
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||||
|
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||||
|
<column name="auth_token" type="text" notnull="true"/>
|
||||||
|
<column name="issued_at" type="localdatetime" notnull="true"/>
|
||||||
|
<column name="expires_at" type="localdatetime" notnull="true"/>
|
||||||
|
<column name="refresh_expires_at" type="localdatetime" notnull="true"/>
|
||||||
|
<column name="refresh_token" type="text" notnull="true"/>
|
||||||
|
<column name="user_id" type="varchar" notnull="true"/>
|
||||||
|
<column name="expired" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="logged_out" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||||
|
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||||
|
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||||
|
<column name="created_by" type="varchar" notnull="true"/>
|
||||||
|
<column name="modified_by" type="varchar" notnull="true"/>
|
||||||
|
</createTable>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="auth_token_cache">
|
||||||
|
<column name="refresh_history" type="jsonb"/>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="product">
|
||||||
|
<column name="id" type="varchar"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
<changeSet type="pendingDrops">
|
||||||
|
<dropColumn columnName="code" tableName="product"/>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="outgoing_inventory">
|
||||||
|
<column name="unloading_plant_id" type="varchar"/>
|
||||||
|
<column name="unloading" type="varchar"/>
|
||||||
|
<column name="job_card" type="varchar"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
<changeSet type="pendingDrops">
|
||||||
|
<dropTable name="sql_model" sequenceCol="sys_pk"/>
|
||||||
|
<dropTable name="vehicle" sequenceCol="sys_pk"/>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<addColumn tableName="purchase_order">
|
||||||
|
<column name="all_loading_site" type="boolean" defaultValue="true" notnull="true"/>
|
||||||
|
<column name="all_unloading_site" type="boolean" defaultValue="true" notnull="true"/>
|
||||||
|
<column name="unloading_plant_id" type="varchar"/>
|
||||||
|
<column name="loading_site_id" type="uuid"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||||
|
<changeSet type="apply">
|
||||||
|
<alterColumn columnName="uom" tableName="product" checkConstraint="check ( uom in ('KG','CFT','TON','LTR','NUMBER','MTR','BOX','CUM','PACKET','ALL','NOS','LITER'))" checkConstraintName="ck_product_uom"/>
|
||||||
|
<alterColumn columnName="all_loading_site" tableName="purchase_order" defaultValue="false"/>
|
||||||
|
<alterColumn columnName="all_unloading_site" tableName="purchase_order" defaultValue="false"/>
|
||||||
|
</changeSet>
|
||||||
|
</migration>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user