Customer Region
Customer Container
Customer Daily Install
Customer Daily Install Container
Customer Daily Order 에 Region 추가.
This commit is contained in:
Hyojin Ahn 2026-05-22 09:56:08 -04:00
parent ac6488b343
commit 98865cb055
34 changed files with 1409 additions and 663 deletions

3
.gitignore vendored
View File

@ -31,3 +31,6 @@ build/
### VS Code ###
.vscode/
/http/
/logs/
/jwt-security.drawio

View File

@ -1,45 +0,0 @@
### Register User
POST http://localhost:8080/api/v1/auth/register
Content-Type: application/json
{
"firstname": "Ali",
"lastname": "Bouali",
"email": "alibou@mail.com",
"password": "password",
"role": "ADMIN"
}
> {% client.global.set("auth-token", response.body.access_token); %}
### Query the Demo endpoint
GET http://localhost:8080/api/v1/demo-controller
Authorization: Bearer {{auth-token}}
### Change the password
PATCH http://localhost:8080/api/v1/users
Content-Type: application/json
Authorization: Bearer {{auth-token}}
{
"currentPassword": "password",
"newPassword": "newPassword",
"confirmationPassword": "newPassword"
}
### Login again and update the token
POST http://localhost:8080/api/v1/auth/authenticate
Content-Type: application/json
{
"email": "alibou@mail.com",
"password": "newPassword"
}
> {% client.global.set("new-auth-token", response.body.access_token); %}
### Query the Demo endpoint after password change
GET http://localhost:8080/api/v1/demo-controller
Authorization: Bearer {{new-auth-token}}

View File

@ -1,17 +0,0 @@
### Register User
POST http://localhost:8080/api/v1/auth/register
Content-Type: application/json
{
"firstname": "Ali",
"lastname": "Bouali",
"email": "alibou21@mail.com",
"password": "password",
"role": "ADMIN"
}
> {% client.global.set("auth-token", response.body.access_token); %}
### Query the Demo endpoint
GET http://localhost:8080/api/v1/demo-controller
Authorization: Bearer {{auth-token}}

View File

@ -1,44 +0,0 @@
### Register User
POST http://localhost:8080/api/v1/auth/register
Content-Type: application/json
{
"firstname": "Ali",
"lastname": "Bouali",
"email": "alibou@mail.com",
"password": "password",
"role": "ADMIN"
}
> {% client.global.set("auth-token", response.body.access_token); %}
###Create a new book
POST http://localhost:8080/api/v1/books
Authorization: Bearer {{auth-token}}
Content-Type: application/json
{
"author": "Alibou",
"isbn": "12345"
}
### Query Books
GET http://localhost:8080/api/v1/books
Authorization: Bearer {{auth-token}}
### Update one book
POST http://localhost:8080/api/v1/books
Authorization: Bearer {{auth-token}}
Content-Type: application/json
{
"id": 1,
"author": "Alibou 2",
"isbn": "12345"
}
### Query the Books one more time
GET http://localhost:8080/api/v1/books
Authorization: Bearer {{auth-token}}

View File

@ -1,517 +0,0 @@
<mxfile host="Electron" modified="2023-04-27T08:53:10.057Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.2.1 Chrome/112.0.5615.87 Electron/24.1.2 Safari/537.36" etag="DDOU9Ve5raWsCyPsviHS" version="21.2.1" type="device" pages="4">
<diagram id="pjGB-ErrghB2Nym8I_LS" name="security-workflow">
<mxGraphModel dx="3194" dy="1214" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="qfr3ut9dFdVh4iJpzXPu-13" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="160" y="30" width="787" height="787" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-14" value="" style="group" parent="qfr3ut9dFdVh4iJpzXPu-13" vertex="1" connectable="0">
<mxGeometry width="787" height="787" as="geometry" />
</mxCell>
<mxCell id="OGfNcUSvT1gZZqw-ERg4-2" value="" style="whiteSpace=wrap;html=1;aspect=fixed;fillColor=#d5e8d4;strokeColor=#82b366;" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry width="787" height="787" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-5" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry x="38" y="116" width="727" height="520" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-16" value="" style="group" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1" connectable="0">
<mxGeometry x="317" y="120" width="124" height="93" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-12" value="" style="sketch=0;html=1;aspect=fixed;strokeColor=none;shadow=0;align=center;verticalAlign=top;fillColor=#3B8DF1;shape=mxgraph.gcp2.systems_check;rounded=0;fontColor=#3399FF;" parent="qfr3ut9dFdVh4iJpzXPu-16" vertex="1">
<mxGeometry x="26.840000000000003" y="26" width="66.33" height="67" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-15" value="UserDetailsService" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#3399FF;fontStyle=1" parent="qfr3ut9dFdVh4iJpzXPu-16" vertex="1">
<mxGeometry x="-3" width="127" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-28" value="" style="group" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1" connectable="0">
<mxGeometry x="182" y="245" width="120" height="112.04615384615384" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-29" value="" style="group" parent="qfr3ut9dFdVh4iJpzXPu-28" vertex="1" connectable="0">
<mxGeometry x="20" width="80" height="82.04615384615384" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-30" value="" style="group" parent="qfr3ut9dFdVh4iJpzXPu-29" vertex="1" connectable="0">
<mxGeometry x="23.200000000000003" y="18.870615384615384" width="32" height="45.12538461538462" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-31" value="" style="verticalLabelPosition=bottom;html=1;verticalAlign=top;align=center;strokeColor=#2D7600;fillColor=#60a917;shape=mxgraph.azure.startup_task;pointerEvents=1;fontSize=14;fontColor=#ffffff;" parent="qfr3ut9dFdVh4iJpzXPu-30" vertex="1">
<mxGeometry width="31.99999999999999" height="45.12538461538462" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-32" value="" style="sketch=0;html=1;aspect=fixed;strokeColor=#2D7600;shadow=0;align=center;verticalAlign=top;fillColor=#60a917;shape=mxgraph.gcp2.check;fontSize=14;fontColor=#ffffff;" parent="qfr3ut9dFdVh4iJpzXPu-30" vertex="1">
<mxGeometry x="3.1971197119711996" y="5.206775147928994" width="9.89152296481915" height="7.9132183718553195" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-33" value="" style="sketch=0;html=1;aspect=fixed;strokeColor=#2D7600;shadow=0;align=center;verticalAlign=top;fillColor=#60a917;shape=mxgraph.gcp2.check;fontSize=14;fontColor=#ffffff;" parent="qfr3ut9dFdVh4iJpzXPu-30" vertex="1">
<mxGeometry x="3.1971197119711996" y="12.149142011834318" width="9.89152296481915" height="7.9132183718553195" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-34" value="" style="rhombus;whiteSpace=wrap;html=1;fontSize=14;fontColor=default;fillColor=none;" parent="qfr3ut9dFdVh4iJpzXPu-29" vertex="1">
<mxGeometry width="80" height="82.04615384615384" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-35" value="Validate JWT" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=14;fontColor=#006600;fontStyle=1" parent="qfr3ut9dFdVh4iJpzXPu-28" vertex="1">
<mxGeometry x="8" y="83.04615384615384" width="104" height="29" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=default;strokeWidth=2;fontColor=#0079d6;" parent="qfr3ut9dFdVh4iJpzXPu-14" source="qfr3ut9dFdVh4iJpzXPu-41" target="qfr3ut9dFdVh4iJpzXPu-44" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-41" value="Security" style="html=1;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.security;rounded=0;" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry x="332" y="374" width="83" height="63" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeColor=#6c8ebf;strokeWidth=2;fontColor=default;fillColor=#dae8fc;" parent="qfr3ut9dFdVh4iJpzXPu-14" source="qfr3ut9dFdVh4iJpzXPu-34" target="qfr3ut9dFdVh4iJpzXPu-41" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-20" value="" style="group" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1" connectable="0">
<mxGeometry x="30.5" y="388" width="115" height="63.4736842105263" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-6" value="&lt;font color=&quot;#3399ff&quot;&gt;Check JWT token&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1" parent="qfr3ut9dFdVh4iJpzXPu-20" vertex="1">
<mxGeometry x="-3" y="37.4736842105263" width="118" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-4" value="" style="verticalLabelPosition=bottom;html=1;verticalAlign=top;align=center;strokeColor=none;fillColor=#00BEF2;shape=mxgraph.azure.startup_task;pointerEvents=1;" parent="qfr3ut9dFdVh4iJpzXPu-20" vertex="1">
<mxGeometry x="32.580357142857146" width="39.441964285714285" height="39.473684210526315" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-43" value="Update the&lt;br&gt;SecurityContextHolder" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#0079d6;fontStyle=1" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry x="303" y="440" width="148" height="41" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=default;strokeWidth=2;fontColor=#0079d6;" parent="qfr3ut9dFdVh4iJpzXPu-14" source="qfr3ut9dFdVh4iJpzXPu-44" target="qfr3ut9dFdVh4iJpzXPu-47" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-44" value="" style="aspect=fixed;perimeter=ellipsePerimeter;html=1;align=center;shadow=0;dashed=0;fontColor=#4277BB;labelBackgroundColor=#ffffff;fontSize=12;spacingTop=3;image;image=img/lib/ibm/vpc/Router.svg;rounded=0;sketch=0;" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry x="575" y="375.5" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-46" value="" style="group" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1" connectable="0">
<mxGeometry x="552" y="504" width="90" height="130" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-47" value="" style="sketch=0;aspect=fixed;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;fillColor=#808080;shape=mxgraph.mscae.enterprise.server_directory;rounded=0;labelBackgroundColor=none;labelBorderColor=none;strokeWidth=2;fontSize=32;fontColor=#3399FF;" parent="qfr3ut9dFdVh4iJpzXPu-46" vertex="1">
<mxGeometry x="18" width="72" height="100" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-48" value="Controller" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontSize=14;fontColor=default;fontStyle=1" parent="qfr3ut9dFdVh4iJpzXPu-46" vertex="1">
<mxGeometry y="100" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-60" value="" style="sketch=0;html=1;aspect=fixed;strokeColor=#82b366;shadow=0;align=center;verticalAlign=top;fillColor=#d5e8d4;shape=mxgraph.gcp2.systems_check;rounded=0;fontColor=#2c8b18;" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry x="328.0032258064516" y="219.9320430107527" width="41.72370967741935" height="42.145161290322584" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-61" value="JwtService" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=#82b366;fillColor=#d5e8d4;fontStyle=1;fontColor=#2c8b18;" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry x="366.00290322580645" y="228" width="81" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;strokeColor=#2D7600;strokeWidth=2;fontColor=#2c8b18;fillColor=#60a917;" parent="qfr3ut9dFdVh4iJpzXPu-14" source="qfr3ut9dFdVh4iJpzXPu-34" target="qfr3ut9dFdVh4iJpzXPu-60" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-66" value="DispatcherServlet" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#8ec53f;" parent="qfr3ut9dFdVh4iJpzXPu-14" vertex="1">
<mxGeometry x="548.5" y="353" width="113" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=default;strokeWidth=2;fontColor=#2c8b18;" parent="1" source="OGfNcUSvT1gZZqw-ERg4-1" target="OGfNcUSvT1gZZqw-ERg4-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OGfNcUSvT1gZZqw-ERg4-1" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=https://seeklogo.com/images/P/postman-logo-F43375A2EB-seeklogo.com.png;" parent="1" vertex="1">
<mxGeometry x="8" y="398.5" width="48.67" height="50" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-1" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=https://4.bp.blogspot.com/-ou-a_Aa1t7A/W6IhNc3Q0gI/AAAAAAAAD6Y/pwh44arKiuM_NBqB1H7Pz4-7QhUxAgZkACLcBGAs/s1600/spring-boot-logo.png;" parent="1" vertex="1">
<mxGeometry x="688.26" y="672" width="150.48" height="79" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-2" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=https://www.turbonomic.com/wp-content/uploads/2022/04/logo_apache-tomcat.png;" parent="1" vertex="1">
<mxGeometry x="268.26" y="676.25" width="130" height="70.5" as="geometry" />
</mxCell>
<mxCell id="OGfNcUSvT1gZZqw-ERg4-11" value="" style="group;" parent="1" vertex="1" connectable="0">
<mxGeometry x="214" y="366" width="98" height="64" as="geometry" />
</mxCell>
<mxCell id="OGfNcUSvT1gZZqw-ERg4-8" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="OGfNcUSvT1gZZqw-ERg4-11" vertex="1">
<mxGeometry width="84" height="48" as="geometry" />
</mxCell>
<mxCell id="OGfNcUSvT1gZZqw-ERg4-9" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="OGfNcUSvT1gZZqw-ERg4-11" vertex="1">
<mxGeometry x="7" y="8" width="84" height="48" as="geometry" />
</mxCell>
<mxCell id="OGfNcUSvT1gZZqw-ERg4-10" value="JwtAuthFilter" style="rounded=0;whiteSpace=wrap;html=1;" parent="OGfNcUSvT1gZZqw-ERg4-11" vertex="1">
<mxGeometry x="14" y="16" width="84" height="48" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-3" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;strokeColor=#000033;strokeWidth=2;fontSize=14;fontColor=default;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="qfr3ut9dFdVh4iJpzXPu-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="398.26" y="702" as="sourcePoint" />
<mxPoint x="673.5" y="712" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontColor=#3399FF;strokeWidth=2;" parent="1" source="OGfNcUSvT1gZZqw-ERg4-8" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="502" y="212" as="targetPoint" />
<Array as="points">
<mxPoint x="284" y="366" />
<mxPoint x="284" y="212" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontColor=#3399FF;strokeWidth=2;" parent="1" source="qfr3ut9dFdVh4iJpzXPu-12" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1080" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-22" value="" style="group" parent="1" vertex="1" connectable="0">
<mxGeometry x="1006.98" y="281" width="133.01999999999998" height="209" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-21" value="" style="aspect=fixed;html=1;points=[];align=center;image;fontSize=12;image=img/lib/azure2/databases/Azure_Database_PostgreSQL_Server.svg;rounded=0;sketch=0;fontColor=#3399FF;" parent="qfr3ut9dFdVh4iJpzXPu-22" vertex="1">
<mxGeometry x="12.019999999999982" width="90.75" height="121" as="geometry" />
</mxCell>
<mxCell id="OGfNcUSvT1gZZqw-ERg4-4" value="" style="shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=https://developers.redhat.com/sites/default/files/styles/article_feature/public/blog/2014/05/homepage-docker-logo.png?itok=zx0e-vcP;" parent="qfr3ut9dFdVh4iJpzXPu-22" vertex="1">
<mxGeometry y="99" width="133.02" height="110" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-24" value="Invalid JWT token" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#e26259;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="56.8" y="230" width="120" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-25" value="Missing JWT" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#e26259;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="76.6" y="288" width="91" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-26" value="User does not exist" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#e26259;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="76.6" y="311" width="129" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-27" value="HTTP 403" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#e26259;rounded=0;sketch=0;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="1" y="356" width="72" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.959;entryY=0.695;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#0ed60a;strokeWidth=2;fontColor=default;" parent="1" source="qfr3ut9dFdVh4iJpzXPu-21" target="qfr3ut9dFdVh4iJpzXPu-12" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1064" y="223" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0;entryDx=0;entryDy=0;strokeColor=#0ed60a;strokeWidth=2;fontColor=default;" parent="1" source="qfr3ut9dFdVh4iJpzXPu-12" target="OGfNcUSvT1gZZqw-ERg4-8" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="298" y="225" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=default;strokeWidth=2;fontColor=default;" parent="1" source="OGfNcUSvT1gZZqw-ERg4-10" target="qfr3ut9dFdVh4iJpzXPu-34" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#d50c0b;strokeWidth=2;fontColor=default;" parent="1" source="qfr3ut9dFdVh4iJpzXPu-34" target="OGfNcUSvT1gZZqw-ERg4-1" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="402" y="259" />
<mxPoint x="32" y="259" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-53" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#3c8df1;strokeWidth=2;fontColor=#0079d6;startArrow=none;" parent="1" source="qfr3ut9dFdVh4iJpzXPu-55" target="OGfNcUSvT1gZZqw-ERg4-1" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-55" value="" style="dashed=0;outlineConnect=0;html=1;align=center;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;shape=mxgraph.weblogos.json_2;rounded=0;sketch=0;fontColor=#0079d6;" parent="1" vertex="1">
<mxGeometry x="76.60000000000002" y="571.4" width="80.4" height="25.200000000000003" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-56" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#3c8df1;strokeWidth=2;fontColor=#0079d6;endArrow=none;" parent="1" source="qfr3ut9dFdVh4iJpzXPu-47" target="qfr3ut9dFdVh4iJpzXPu-55" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="730" y="584.0322580645161" as="sourcePoint" />
<mxPoint x="32.322580645161224" y="448.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-57" value="HTTP 200" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=#0079d6;fontStyle=1" parent="1" vertex="1">
<mxGeometry y="464" width="72" height="26" as="geometry" />
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;sketch=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;strokeColor=#d40d0b;strokeWidth=2;fontColor=#d40d0b;" parent="1" source="OGfNcUSvT1gZZqw-ERg4-8" target="OGfNcUSvT1gZZqw-ERg4-1" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="214" y="287" />
<mxPoint x="32" y="287" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qfr3ut9dFdVh4iJpzXPu-65" value="HTTP Requests" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontColor=default;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="45" y="425" width="106" height="26" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="sBTO1LKfppjqILYJjrTV" name="new-flow">
<mxGraphModel dx="2229" dy="1045" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="HA8-pInTj3ZK-7nUhY4h-1" value="" style="group;fillColor=default;strokeColor=none;" parent="1" vertex="1" connectable="0">
<mxGeometry x="60" y="360" width="180" height="90" as="geometry" />
</mxCell>
<mxCell id="QRnQFyGs-lFjeeRuztLu-1" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="HA8-pInTj3ZK-7nUhY4h-1" vertex="1">
<mxGeometry width="160" height="70" as="geometry" />
</mxCell>
<mxCell id="QRnQFyGs-lFjeeRuztLu-2" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="HA8-pInTj3ZK-7nUhY4h-1" vertex="1">
<mxGeometry x="10" y="10" width="160" height="70" as="geometry" />
</mxCell>
<mxCell id="QRnQFyGs-lFjeeRuztLu-3" value="JwtAuthFilter" style="rounded=0;whiteSpace=wrap;html=1;" parent="HA8-pInTj3ZK-7nUhY4h-1" vertex="1">
<mxGeometry x="20" y="20" width="160" height="70" as="geometry" />
</mxCell>
<mxCell id="OrCYgKApnLObKEuBMM75-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="OrCYgKApnLObKEuBMM75-1" target="OrCYgKApnLObKEuBMM75-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OrCYgKApnLObKEuBMM75-1" value="JwtService" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
<mxGeometry x="400" y="330" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="OrCYgKApnLObKEuBMM75-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="OrCYgKApnLObKEuBMM75-2" target="OrCYgKApnLObKEuBMM75-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OrCYgKApnLObKEuBMM75-2" value="TokenRepository" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="400" y="430" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="OrCYgKApnLObKEuBMM75-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" parent="1" source="QRnQFyGs-lFjeeRuztLu-3" target="OrCYgKApnLObKEuBMM75-1" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="OrCYgKApnLObKEuBMM75-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" parent="1" source="QRnQFyGs-lFjeeRuztLu-3" target="OrCYgKApnLObKEuBMM75-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="EAdGHvd8W2WM0f3SbvN2-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="OrCYgKApnLObKEuBMM75-5" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="920" y="405" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="EAdGHvd8W2WM0f3SbvN2-6" value="Valid token" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="EAdGHvd8W2WM0f3SbvN2-2" vertex="1" connectable="0">
<mxGeometry x="-0.319" y="1" relative="1" as="geometry">
<mxPoint x="13" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="EAdGHvd8W2WM0f3SbvN2-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;fillColor=#f8cecc;strokeColor=#b85450;" parent="1" source="OrCYgKApnLObKEuBMM75-5" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="740" y="200" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="EAdGHvd8W2WM0f3SbvN2-5" value="Invalid token" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="EAdGHvd8W2WM0f3SbvN2-4" vertex="1" connectable="0">
<mxGeometry x="-0.1919" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="OrCYgKApnLObKEuBMM75-5" value="Calculate" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="700" y="365" width="80" height="80" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="JHzdb8y7AclNLFwD1zrP" name="class-diagram">
<mxGraphModel dx="2229" dy="1045" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="XC6CGuYQlSzaP45YXhiZ-1" value="User" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;fillColor=default;" parent="1" vertex="1">
<mxGeometry x="344" y="259" width="180" height="210" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-2" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="XC6CGuYQlSzaP45YXhiZ-1" vertex="1">
<mxGeometry y="30" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-3" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-2" vertex="1">
<mxGeometry width="60" height="30" as="geometry">
<mxRectangle width="60" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-4" value="id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-2" vertex="1">
<mxGeometry x="60" width="120" height="30" as="geometry">
<mxRectangle width="120" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-5" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-1" vertex="1">
<mxGeometry y="60" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-6" value="String" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-5" vertex="1">
<mxGeometry width="60" height="30" as="geometry">
<mxRectangle width="60" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-7" value="firstName" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-5" vertex="1">
<mxGeometry x="60" width="120" height="30" as="geometry">
<mxRectangle width="120" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-8" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-1" vertex="1">
<mxGeometry y="90" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-9" value="String" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-8" vertex="1">
<mxGeometry width="60" height="30" as="geometry">
<mxRectangle width="60" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-10" value="lastName" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-8" vertex="1">
<mxGeometry x="60" width="120" height="30" as="geometry">
<mxRectangle width="120" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-11" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-1" vertex="1">
<mxGeometry y="120" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-12" value="String" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-11" vertex="1">
<mxGeometry width="60" height="30" as="geometry">
<mxRectangle width="60" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-13" value="email" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-11" vertex="1">
<mxGeometry x="60" width="120" height="30" as="geometry">
<mxRectangle width="120" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-32" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-1" vertex="1">
<mxGeometry y="150" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-33" value="String" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-32" vertex="1">
<mxGeometry width="60" height="30" as="geometry">
<mxRectangle width="60" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-34" value="password" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-32" vertex="1">
<mxGeometry x="60" width="120" height="30" as="geometry">
<mxRectangle width="120" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-35" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-1" vertex="1">
<mxGeometry y="180" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-36" value="String" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-35" vertex="1">
<mxGeometry width="60" height="30" as="geometry">
<mxRectangle width="60" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-37" value="role" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-35" vertex="1">
<mxGeometry x="60" width="120" height="30" as="geometry">
<mxRectangle width="120" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-14" value="Token" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;fillColor=default;" parent="1" vertex="1">
<mxGeometry x="645" y="389" width="180" height="180" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-15" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="XC6CGuYQlSzaP45YXhiZ-14" vertex="1">
<mxGeometry y="30" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-16" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-15" vertex="1">
<mxGeometry width="49" height="30" as="geometry">
<mxRectangle width="49" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-17" value="id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-15" vertex="1">
<mxGeometry x="49" width="131" height="30" as="geometry">
<mxRectangle width="131" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-18" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-14" vertex="1">
<mxGeometry y="60" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-19" value="String" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-18" vertex="1">
<mxGeometry width="49" height="30" as="geometry">
<mxRectangle width="49" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-20" value="token" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-18" vertex="1">
<mxGeometry x="49" width="131" height="30" as="geometry">
<mxRectangle width="131" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-21" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-14" vertex="1">
<mxGeometry y="90" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-22" value="String" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-21" vertex="1">
<mxGeometry width="49" height="30" as="geometry">
<mxRectangle width="49" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-23" value="tokenType" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-21" vertex="1">
<mxGeometry x="49" width="131" height="30" as="geometry">
<mxRectangle width="131" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-28" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-14" vertex="1">
<mxGeometry y="120" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-29" value="boolean" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-28" vertex="1">
<mxGeometry width="49" height="30" as="geometry">
<mxRectangle width="49" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-30" value="expired" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-28" vertex="1">
<mxGeometry x="49" width="131" height="30" as="geometry">
<mxRectangle width="131" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-24" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="XC6CGuYQlSzaP45YXhiZ-14" vertex="1">
<mxGeometry y="150" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-25" value="boolean" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-24" vertex="1">
<mxGeometry width="49" height="30" as="geometry">
<mxRectangle width="49" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-26" value="revoked" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;" parent="XC6CGuYQlSzaP45YXhiZ-24" vertex="1">
<mxGeometry x="49" width="131" height="30" as="geometry">
<mxRectangle width="131" height="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="XC6CGuYQlSzaP45YXhiZ-31" value="" style="edgeStyle=entityRelationEdgeStyle;fontSize=12;html=1;endArrow=ERoneToMany;rounded=0;strokeWidth=1;" parent="1" edge="1">
<mxGeometry width="100" height="100" relative="1" as="geometry">
<mxPoint x="524" y="343" as="sourcePoint" />
<mxPoint x="644" y="479" as="targetPoint" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="P7HX4lKzGpJc8V-NnKQx" name="roles and permissions">
<mxGraphModel dx="903" dy="446" grid="0" gridSize="10" guides="1" tooltips="1" connect="0" arrows="0" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-17" value="Roles and Permissions" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=23;fontStyle=1" vertex="1" parent="1">
<mxGeometry x="233" y="213" width="688" height="417" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="LGTntW4OqFH9rOVflEHm-1" target="LGTntW4OqFH9rOVflEHm-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;curved=1;" edge="1" parent="1" source="LGTntW4OqFH9rOVflEHm-1" target="Fkp4l_HLPrJYwHj4Cqq2-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="LGTntW4OqFH9rOVflEHm-1" value="User" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="332" y="396" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="LGTntW4OqFH9rOVflEHm-2" target="LGTntW4OqFH9rOVflEHm-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="LGTntW4OqFH9rOVflEHm-2" target="Fkp4l_HLPrJYwHj4Cqq2-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="LGTntW4OqFH9rOVflEHm-2" target="Fkp4l_HLPrJYwHj4Cqq2-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="LGTntW4OqFH9rOVflEHm-2" target="Fkp4l_HLPrJYwHj4Cqq2-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="LGTntW4OqFH9rOVflEHm-2" value="ROLE_A" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="467" y="329" width="110" height="36" as="geometry" />
</mxCell>
<mxCell id="LGTntW4OqFH9rOVflEHm-3" value="RESOURCE:READ" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="640" y="272" width="128" height="27" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-1" value="RESOURCE:WRITE" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="640" y="312" width="128" height="27" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-2" value="RESOURCE:DELETE" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
<mxGeometry x="640" y="352" width="128" height="27" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-3" value="RESOURCE:UPDATE" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="640" y="392" width="128" height="27" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Fkp4l_HLPrJYwHj4Cqq2-12" target="Fkp4l_HLPrJYwHj4Cqq2-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Fkp4l_HLPrJYwHj4Cqq2-12" target="Fkp4l_HLPrJYwHj4Cqq2-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Fkp4l_HLPrJYwHj4Cqq2-12" target="Fkp4l_HLPrJYwHj4Cqq2-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Fkp4l_HLPrJYwHj4Cqq2-12" target="Fkp4l_HLPrJYwHj4Cqq2-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-12" value="ROLE_B" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="467" y="489" width="110" height="36" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-13" value="RESOURCE:READ" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="640" y="432" width="128" height="27" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-14" value="RESOURCE:WRITE" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="640" y="472" width="128" height="27" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-15" value="RESOURCE:DELETE" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
<mxGeometry x="640" y="512" width="128" height="27" as="geometry" />
</mxCell>
<mxCell id="Fkp4l_HLPrJYwHj4Cqq2-16" value="RESOURCE:UPDATE" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="640" y="552" width="128" height="27" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -1,25 +0,0 @@
2026-05-20T08:25:45.241-04:00 INFO 5596 --- [main] com.goi.erp.SecurityApplication : Starting SecurityApplication using Java 17.0.16 with PID 5596 (D:\workspace-eclipse\crm-rest-api\target\classes started by Hyojin Ahn in D:\workspace-eclipse\crm-rest-api)
2026-05-20T08:25:45.246-04:00 INFO 5596 --- [main] com.goi.erp.SecurityApplication : The following 1 profile is active: "default"
2026-05-20T08:25:45.694-04:00 INFO 5596 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2026-05-20T08:25:45.786-04:00 INFO 5596 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 87 ms. Found 3 JPA repository interfaces.
2026-05-20T08:25:46.383-04:00 INFO 5596 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8082 (http)
2026-05-20T08:25:46.389-04:00 INFO 5596 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2026-05-20T08:25:46.389-04:00 INFO 5596 --- [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.13]
2026-05-20T08:25:46.457-04:00 INFO 5596 --- [main] o.a.c.c.C.[.[localhost].[/crm-rest-api] : Initializing Spring embedded WebApplicationContext
2026-05-20T08:25:46.457-04:00 INFO 5596 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1173 ms
2026-05-20T08:25:46.602-04:00 INFO 5596 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2026-05-20T08:25:46.632-04:00 INFO 5596 --- [main] org.hibernate.Version : HHH000412: Hibernate ORM core version 6.2.9.Final
2026-05-20T08:25:46.635-04:00 INFO 5596 --- [main] org.hibernate.cfg.Environment : HHH000406: Using bytecode reflection optimizer
2026-05-20T08:25:46.716-04:00 INFO 5596 --- [main] o.h.b.i.BytecodeProviderInitiator : HHH000021: Bytecode provider name : bytebuddy
2026-05-20T08:25:46.783-04:00 INFO 5596 --- [main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer
2026-05-20T08:25:46.793-04:00 INFO 5596 --- [main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2026-05-20T08:25:46.891-04:00 INFO 5596 --- [main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@674e4c82
2026-05-20T08:25:46.892-04:00 INFO 5596 --- [main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2026-05-20T08:25:47.044-04:00 INFO 5596 --- [main] o.h.b.i.BytecodeProviderInitiator : HHH000021: Bytecode provider name : bytebuddy
2026-05-20T08:25:47.499-04:00 INFO 5596 --- [main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2026-05-20T08:25:47.549-04:00 INFO 5596 --- [main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2026-05-20T08:25:47.931-04:00 WARN 5596 --- [main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2026-05-20T08:25:48.177-04:00 INFO 5596 --- [main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 1 endpoint(s) beneath base path '/actuator'
2026-05-20T08:25:48.210-04:00 INFO 5596 --- [main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@466fd19b, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@348d1a5e, org.springframework.security.web.context.SecurityContextHolderFilter@3fc92211, org.springframework.security.web.header.HeaderWriterFilter@227ae4e4, org.springframework.security.web.authentication.logout.LogoutFilter@3ae5cbb9, org.springframework.web.filter.CorsFilter@7f746160, com.goi.erp.config.JwtAuthenticationFilter@16ea0f22, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@117bfeb8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@31aec04a, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@17524c36, org.springframework.security.web.session.SessionManagementFilter@440309c5, org.springframework.security.web.access.ExceptionTranslationFilter@1b2213b2, org.springframework.security.web.access.intercept.AuthorizationFilter@24e0bdb]
2026-05-20T08:25:48.496-04:00 INFO 5596 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8082 (http) with context path '/crm-rest-api'
2026-05-20T08:25:48.505-04:00 INFO 5596 --- [main] com.goi.erp.SecurityApplication : Started SecurityApplication in 3.548 seconds (process running for 3.992)

View File

@ -13,6 +13,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@ -32,13 +33,22 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
@NonNull FilterChain filterChain
) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
String jwt = null;
final String jwt = authHeader.substring(7);
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if ("AUTH_TOKEN".equals(cookie.getName())) {
jwt = cookie.getValue();
break;
}
}
}
if (jwt == null || jwt.isBlank()) {
filterChain.doFilter(request, response);
return;
}
try {
// 기존 인증 정보 확인

View File

@ -0,0 +1,93 @@
package com.goi.erp.controller;
import com.goi.erp.common.permission.PermissionChecker;
import com.goi.erp.common.permission.PermissionSet;
import com.goi.erp.dto.CustomerContainerRequestDto;
import com.goi.erp.dto.CustomerContainerResponseDto;
import com.goi.erp.service.CustomerContainerService;
import com.goi.erp.token.PermissionAuthenticationToken;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/customer-container")
@RequiredArgsConstructor
public class CustomerContainerController {
private final CustomerContainerService service;
private PermissionSet getPermission() {
PermissionAuthenticationToken auth =
(PermissionAuthenticationToken)
SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission missing");
}
return auth.getPermissionSet();
}
@PostMapping
public ResponseEntity<CustomerContainerResponseDto> create(
@RequestBody CustomerContainerRequestDto dto
) {
if (!PermissionChecker.canCreateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return new ResponseEntity<>(
service.create(dto),
HttpStatus.CREATED
);
}
@GetMapping("/customer/{customerId}")
public ResponseEntity<List<CustomerContainerResponseDto>> getByCustomerId(
@PathVariable Long customerId
) {
if (!PermissionChecker.canReadCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(service.getByCustomerId(customerId));
}
@PatchMapping("/{id}")
public ResponseEntity<CustomerContainerResponseDto> update(
@PathVariable Long id,
@RequestBody CustomerContainerRequestDto dto
) {
if (!PermissionChecker.canUpdateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(service.update(id, dto));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
if (!PermissionChecker.canDeleteCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
service.delete(id);
return ResponseEntity.noContent().build();
}
}

View File

@ -0,0 +1,96 @@
package com.goi.erp.controller;
import com.goi.erp.common.permission.PermissionChecker;
import com.goi.erp.common.permission.PermissionSet;
import com.goi.erp.dto.CustomerDailyInstallContainerRequestDto;
import com.goi.erp.dto.CustomerDailyInstallContainerResponseDto;
import com.goi.erp.service.CustomerDailyInstallContainerService;
import com.goi.erp.token.PermissionAuthenticationToken;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/customer-daily-install-container")
@RequiredArgsConstructor
public class CustomerDailyInstallContainerController {
private final CustomerDailyInstallContainerService service;
private PermissionSet getPermission() {
PermissionAuthenticationToken auth =
(PermissionAuthenticationToken)
SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission missing");
}
return auth.getPermissionSet();
}
@PostMapping
public ResponseEntity<CustomerDailyInstallContainerResponseDto> create(
@RequestBody CustomerDailyInstallContainerRequestDto dto
) {
if (!PermissionChecker.canCreateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return new ResponseEntity<>(
service.create(dto),
HttpStatus.CREATED
);
}
@GetMapping("/daily-install/{dailyInstallId}")
public ResponseEntity<List<CustomerDailyInstallContainerResponseDto>>
getByDailyInstallId(
@PathVariable Long dailyInstallId
) {
if (!PermissionChecker.canReadCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(
service.getByDailyInstallId(dailyInstallId)
);
}
@PatchMapping("/{id}")
public ResponseEntity<CustomerDailyInstallContainerResponseDto> update(
@PathVariable Long id,
@RequestBody CustomerDailyInstallContainerRequestDto dto
) {
if (!PermissionChecker.canUpdateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(service.update(id, dto));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
if (!PermissionChecker.canDeleteCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
service.delete(id);
return ResponseEntity.noContent().build();
}
}

View File

@ -0,0 +1,99 @@
package com.goi.erp.controller;
import com.goi.erp.common.permission.PermissionChecker;
import com.goi.erp.common.permission.PermissionSet;
import com.goi.erp.dto.CustomerDailyInstallRequestDto;
import com.goi.erp.dto.CustomerDailyInstallResponseDto;
import com.goi.erp.service.CustomerDailyInstallService;
import com.goi.erp.token.PermissionAuthenticationToken;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.List;
@RestController
@RequestMapping("/customer-daily-install")
@RequiredArgsConstructor
public class CustomerDailyInstallController {
private final CustomerDailyInstallService service;
private PermissionSet getPermission() {
PermissionAuthenticationToken auth =
(PermissionAuthenticationToken)
SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission missing");
}
return auth.getPermissionSet();
}
@PostMapping
public ResponseEntity<CustomerDailyInstallResponseDto> create(
@RequestBody CustomerDailyInstallRequestDto dto
) {
if (!PermissionChecker.canCreateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return new ResponseEntity<>(
service.create(dto),
HttpStatus.CREATED
);
}
@GetMapping("/date/{installDate}")
public ResponseEntity<List<CustomerDailyInstallResponseDto>> getByInstallDate(
@PathVariable
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
LocalDate installDate
) {
if (!PermissionChecker.canReadCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(
service.getByInstallDate(installDate)
);
}
@PatchMapping("/{id}")
public ResponseEntity<CustomerDailyInstallResponseDto> update(
@PathVariable Long id,
@RequestBody CustomerDailyInstallRequestDto dto
) {
if (!PermissionChecker.canUpdateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(service.update(id, dto));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
if (!PermissionChecker.canDeleteCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
service.delete(id);
return ResponseEntity.noContent().build();
}
}

View File

@ -0,0 +1,103 @@
package com.goi.erp.controller;
import com.goi.erp.common.permission.PermissionChecker;
import com.goi.erp.common.permission.PermissionSet;
import com.goi.erp.dto.CustomerRegionRequestDto;
import com.goi.erp.dto.CustomerRegionResponseDto;
import com.goi.erp.service.CustomerRegionService;
import com.goi.erp.token.PermissionAuthenticationToken;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/customer-region")
@RequiredArgsConstructor
public class CustomerRegionController {
private final CustomerRegionService service;
private PermissionSet getPermission() {
PermissionAuthenticationToken auth =
(PermissionAuthenticationToken)
SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission information is missing");
}
return auth.getPermissionSet();
}
@PostMapping
public ResponseEntity<CustomerRegionResponseDto> create(
@RequestBody CustomerRegionRequestDto dto
) {
if (!PermissionChecker.canCreateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return new ResponseEntity<>(
service.create(dto),
HttpStatus.CREATED
);
}
@GetMapping
public ResponseEntity<List<CustomerRegionResponseDto>> getAll() {
if (!PermissionChecker.canReadCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(service.getAll());
}
@GetMapping("/{id}")
public ResponseEntity<CustomerRegionResponseDto> getById(
@PathVariable Long id
) {
if (!PermissionChecker.canReadCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(service.getById(id));
}
@PatchMapping("/{id}")
public ResponseEntity<CustomerRegionResponseDto> update(
@PathVariable Long id,
@RequestBody CustomerRegionRequestDto dto
) {
if (!PermissionChecker.canUpdateCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
return ResponseEntity.ok(service.update(id, dto));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
if (!PermissionChecker.canDeleteCRM(getPermission())) {
throw new AccessDeniedException("No permission");
}
service.delete(id);
return ResponseEntity.noContent().build();
}
}

View File

@ -0,0 +1,42 @@
package com.goi.erp.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerContainerRequestDto {
private Long ccoCustomerId;
private String ccoType;
private Integer ccoCapacity;
private String ccoOwnerType;
private String ccoIsUsed;
private String ccoHasLock;
private String ccoHasWheel;
private String ccoHasWoodframe;
private String ccoStatus;
private String ccoCreateddate;
private String ccoUpdateddate;
private String ccoInstallNote;
private String ccoPickupNote;
private LocalDate ccoInstallDate;
private LocalDate ccoPickupDate;
private LocalDateTime ccoInstallAt;
private LocalDateTime ccoPickupAt;
}

View File

@ -0,0 +1,46 @@
package com.goi.erp.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerContainerResponseDto {
private Long ccoId;
private Long ccoCustomerId;
private String ccoType;
private Integer ccoCapacity;
private String ccoOwnerType;
private String ccoIsUsed;
private String ccoHasLock;
private String ccoHasWheel;
private String ccoHasWoodframe;
private String ccoStatus;
private String ccoCreateddate;
private String ccoUpdateddate;
private String ccoInstallNote;
private String ccoPickupNote;
private LocalDate ccoInstallDate;
private LocalDate ccoPickupDate;
private LocalDateTime ccoInstallAt;
private LocalDateTime ccoPickupAt;
private LocalDateTime ccoModifiedAt;
}

View File

@ -0,0 +1,31 @@
package com.goi.erp.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerDailyInstallContainerRequestDto {
private Long cdicDailyInstallId;
private String cdicAction;
private String cdicType;
private Integer cdicCapacity;
private String cdicIsUsed;
private String cdicHasLock;
private String cdicHasWheel;
private String cdicHasWoodframe;
private String cdicOwnerType;
}

View File

@ -0,0 +1,33 @@
package com.goi.erp.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerDailyInstallContainerResponseDto {
private Long cdicId;
private Long cdicDailyInstallId;
private String cdicAction;
private String cdicType;
private Integer cdicCapacity;
private String cdicIsUsed;
private String cdicHasLock;
private String cdicHasWheel;
private String cdicHasWoodframe;
private String cdicOwnerType;
}

View File

@ -0,0 +1,63 @@
package com.goi.erp.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerDailyInstallRequestDto {
private Integer cdiOrderSeq;
private Long cdiDriverId;
private LocalDate cdiInstallDate;
private LocalTime cdiInstallTime;
private Long cdiCustomerId;
private String cdiAccountNo;
private String cdiCustomerName;
private String cdiPhone;
private String cdiAddress;
private String cdiCity;
private String cdiPostalCode;
private BigDecimal cdiGeoLat;
private BigDecimal cdiGeoLon;
private Long cdiCustomerDriverId;
private String cdiWorkType;
private Integer cdiOilPickup;
private Integer cdiSludge;
private String cdiRequestNote;
private String cdiWorkNote;
private String cdiInstallNote;
private String cdiCsNote;
private String cdiStatus;
private String cdiCreatedBy;
}

View File

@ -0,0 +1,46 @@
package com.goi.erp.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.UUID;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerDailyInstallResponseDto {
private UUID cdiUuid; // UUID
private Integer cdiOrderSeq;
private Long cdiDriverId;
private LocalDate cdiInstallDate;
private LocalTime cdiInstallTime;
private Long cdiCustomerId;
private String cdiAccountNo;
private String cdiCustomerName;
private String cdiPhone;
private String cdiAddress;
private String cdiCity;
private String cdiPostalCode;
private BigDecimal cdiGeoLat;
private BigDecimal cdiGeoLon;
private Long cdiCustomerDriverId;
private String cdiWorkType;
private Integer cdiOilPickup;
private Integer cdiSludge;
private String cdiRequestNote;
private String cdiWorkNote;
private String cdiInstallNote;
private String cdiCsNote;
private String cdiStatus;
private String cdiCreatedBy;
private LocalDateTime cdiCreatedAt;
private LocalDateTime cdiUpdatedAt;
}

View File

@ -12,14 +12,16 @@ import java.util.UUID;
@NoArgsConstructor
public class CustomerDailyOrderRequestDto {
private LocalDate cdoOrderDate; // 주문 날짜 (YYYY-MM-DD)
private String cdoOrderType; // 주문 타입 ('N' )
private String cdoRequestNote; // 주문 요청 메모
private LocalDate cdoOrderDate; // 주문 날짜 (YYYY-MM-DD)
private String cdoJobType; // UCO | INSTALL
private String cdoOrderType; // 주문 타입 ('N' )
private String cdoRequestNote; // 주문 요청 메모
private String cdoExternalDriverId; // MIS 에서 driverId 호출해서 employee_external_map 참조해야함
private String cdoExternalCreatedBy; // MIS 에서 memberId 호출해서 employee_external_map 참조해야함
private Long cdoDriverId; // 배정된 driver id
private UUID cdoDriverUuid; // ERP 에서는 uuid 호출
private Long cdoCustomerId; // 고객 ID
private Long cdoRegionId; // 배정 지역
private Long cdoDriverId; // 배정된 driver id
private UUID cdoDriverUuid; // ERP 에서는 uuid 호출
private Long cdoCustomerId; // 고객 ID
private String cdoCustomerNo;
private UUID cdoCustomerUuid;
private String cdoPaymentType; // 결제 타입

View File

@ -17,10 +17,12 @@ import java.util.UUID;
public class CustomerDailyOrderResponseDto {
private UUID cdoUuid; // UUID
private LocalDate cdoOrderDate; // YYYYMMDD
private LocalDate cdoOrderDate; // YYYYMMDD
private String cdoJobType; // UCO | INSTALL
private String cdoOrderType; // 주문 타입
private String cdoRequestNote; // 요청 메모
//private Long cdoDriverId; // Driver ID
private Long cdoRegionId; // 지역 ID
private Long cdoDriverId; // Driver ID
//private Long cdoCustomerId; //
private String cdoCustomerNo;
private String cdoPaymentType; // 결제 방식

View File

@ -0,0 +1,84 @@
package com.goi.erp.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Entity
@Table(schema = "crm", name = "customer_container")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerContainer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cco_id")
private Long ccoId;
@Column(name = "cco_customer_id", nullable = false)
private Long ccoCustomerId;
@Column(name = "cco_type", nullable = false, length = 10)
private String ccoType;
@Column(name = "cco_capacity")
private Integer ccoCapacity;
@Column(name = "cco_owner_type", length = 1)
private String ccoOwnerType;
@Column(name = "cco_is_used", length = 1)
private String ccoIsUsed;
@Column(name = "cco_has_lock", length = 1)
private String ccoHasLock;
@Column(name = "cco_has_wheel", length = 1)
private String ccoHasWheel;
@Column(name = "cco_has_woodframe", length = 1)
private String ccoHasWoodframe;
@Column(name = "cco_status", length = 1)
private String ccoStatus;
@Column(name = "cco_createddate", length = 14)
private String ccoCreateddate;
@Column(name = "cco_updateddate", length = 14)
private String ccoUpdateddate;
@Column(name = "cco_install_note", length = 500)
private String ccoInstallNote;
@Column(name = "cco_pickup_note", length = 500)
private String ccoPickupNote;
@Column(name = "cco_install_date")
private LocalDate ccoInstallDate;
@Column(name = "cco_pickup_date")
private LocalDate ccoPickupDate;
@Column(name = "cco_install_at")
private LocalDateTime ccoInstallAt;
@Column(name = "cco_pickup_at")
private LocalDateTime ccoPickupAt;
@Column(name = "cco_modified_at")
private LocalDateTime ccoModifiedAt;
}

View File

@ -0,0 +1,110 @@
package com.goi.erp.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.UUID;
@Entity
@Table(schema = "crm", name = "customer_daily_install")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerDailyInstall {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cdi_id")
private Long cdiId;
private UUID cdiUuid;
@Column(name = "cdi_order_seq", nullable = false)
private Integer cdiOrderSeq;
@Column(name = "cdi_driver_id", nullable = false)
private Long cdiDriverId;
@Column(name = "cdi_install_date", nullable = false)
private LocalDate cdiInstallDate;
@Column(name = "cdi_install_time")
private LocalTime cdiInstallTime;
@Column(name = "cdi_customer_id", nullable = false)
private Long cdiCustomerId;
@Column(name = "cdi_account_no", length = 20)
private String cdiAccountNo;
@Column(name = "cdi_customer_name", length = 100)
private String cdiCustomerName;
@Column(name = "cdi_phone", length = 50)
private String cdiPhone;
@Column(name = "cdi_address", length = 200)
private String cdiAddress;
@Column(name = "cdi_city", length = 50)
private String cdiCity;
@Column(name = "cdi_postal_code", length = 20)
private String cdiPostalCode;
@Column(name = "cdi_geo_lat", precision = 10, scale = 8)
private BigDecimal cdiGeoLat;
@Column(name = "cdi_geo_lon", precision = 11, scale = 8)
private BigDecimal cdiGeoLon;
@Column(name = "cdi_customer_driver_id")
private Long cdiCustomerDriverId;
@Column(name = "cdi_work_type", length = 10)
private String cdiWorkType;
@Column(name = "cdi_oil_pickup")
private Integer cdiOilPickup;
@Column(name = "cdi_sludge")
private Integer cdiSludge;
@Column(name = "cdi_request_note")
private String cdiRequestNote;
@Column(name = "cdi_work_note")
private String cdiWorkNote;
@Column(name = "cdi_install_note")
private String cdiInstallNote;
@Column(name = "cdi_cs_note")
private String cdiCsNote;
@Column(name = "cdi_status", length = 1)
private String cdiStatus;
@Column(name = "cdi_created_by", length = 50)
private String cdiCreatedBy;
@Column(name = "cdi_created_at")
private LocalDateTime cdiCreatedAt;
@Column(name = "cdi_updated_at")
private LocalDateTime cdiUpdatedAt;
}

View File

@ -0,0 +1,54 @@
package com.goi.erp.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(schema = "crm", name = "customer_daily_install_container")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerDailyInstallContainer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cdic_id")
private Long cdicId;
@Column(name = "cdic_daily_install_id", nullable = false)
private Long cdicDailyInstallId;
@Column(name = "cdic_action", nullable = false, length = 10)
private String cdicAction;
@Column(name = "cdic_type", nullable = false, length = 10)
private String cdicType;
@Column(name = "cdic_capacity")
private Integer cdicCapacity;
@Column(name = "cdic_is_used", length = 1)
private String cdicIsUsed;
@Column(name = "cdic_has_lock", length = 1)
private String cdicHasLock;
@Column(name = "cdic_has_wheel", length = 1)
private String cdicHasWheel;
@Column(name = "cdic_has_woodframe", length = 1)
private String cdicHasWoodframe;
@Column(name = "cdic_owner_type", length = 1)
private String cdicOwnerType;
}

View File

@ -40,11 +40,14 @@ public class CustomerDailyOrder {
private LocalDate cdoOrderDate;
private String cdoJobType;
@Column(length = 1)
private String cdoOrderType;
private String cdoRequestNote;
private Long cdoRegionId;
private Long cdoDriverId;
private Long cdoCustomerId;

View File

@ -0,0 +1,15 @@
package com.goi.erp.repository;
import com.goi.erp.entity.CustomerContainer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CustomerContainerRepository extends JpaRepository<CustomerContainer, Long> {
List<CustomerContainer> findByCcoCustomerId(Long ccoCustomerId);
List<CustomerContainer> findByCcoCustomerIdAndCcoStatus(Long ccoCustomerId, String ccoStatus);
}

View File

@ -0,0 +1,19 @@
package com.goi.erp.repository;
import com.goi.erp.entity.CustomerDailyInstallContainer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CustomerDailyInstallContainerRepository
extends JpaRepository<CustomerDailyInstallContainer, Long> {
List<CustomerDailyInstallContainer> findByCdicDailyInstallId(Long cdicDailyInstallId);
List<CustomerDailyInstallContainer> findByCdicDailyInstallIdAndCdicAction(
Long cdicDailyInstallId,
String cdicAction
);
}

View File

@ -0,0 +1,25 @@
package com.goi.erp.repository;
import com.goi.erp.entity.CustomerDailyInstall;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List;
@Repository
public interface CustomerDailyInstallRepository extends JpaRepository<CustomerDailyInstall, Long> {
List<CustomerDailyInstall> findByCdiInstallDate(LocalDate cdiInstallDate);
List<CustomerDailyInstall> findByCdiDriverId(Long cdiDriverId);
List<CustomerDailyInstall> findByCdiDriverIdAndCdiInstallDate(
Long cdiDriverId,
LocalDate cdiInstallDate
);
List<CustomerDailyInstall> findByCdiCustomerId(Long cdiCustomerId);
List<CustomerDailyInstall> findByCdiStatus(String cdiStatus);
}

View File

@ -0,0 +1,15 @@
package com.goi.erp.repository;
import com.goi.erp.entity.CustomerRegion;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CustomerRegionRepository extends JpaRepository<CustomerRegion, Long> {
List<CustomerRegion> findByCreStatus(String creStatus);
boolean existsByCreName(String creName);
}

View File

@ -0,0 +1,101 @@
package com.goi.erp.service;
import com.goi.erp.dto.CustomerContainerRequestDto;
import com.goi.erp.dto.CustomerContainerResponseDto;
import com.goi.erp.entity.CustomerContainer;
import com.goi.erp.repository.CustomerContainerRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class CustomerContainerService {
private final CustomerContainerRepository customerContainerRepository;
public CustomerContainerResponseDto create(CustomerContainerRequestDto dto) {
CustomerContainer entity = CustomerContainer.builder()
.ccoCustomerId(dto.getCcoCustomerId())
.ccoType(dto.getCcoType())
.ccoCapacity(dto.getCcoCapacity())
.ccoOwnerType(dto.getCcoOwnerType())
.ccoIsUsed(dto.getCcoIsUsed())
.ccoHasLock(dto.getCcoHasLock())
.ccoHasWheel(dto.getCcoHasWheel())
.ccoHasWoodframe(dto.getCcoHasWoodframe())
.ccoStatus(dto.getCcoStatus())
.ccoInstallNote(dto.getCcoInstallNote())
.ccoPickupNote(dto.getCcoPickupNote())
.ccoInstallDate(dto.getCcoInstallDate())
.ccoPickupDate(dto.getCcoPickupDate())
.ccoInstallAt(dto.getCcoInstallAt())
.ccoPickupAt(dto.getCcoPickupAt())
.build();
entity = customerContainerRepository.save(entity);
return mapToDto(entity);
}
public List<CustomerContainerResponseDto> getByCustomerId(Long customerId) {
return customerContainerRepository.findByCcoCustomerId(customerId)
.stream()
.map(this::mapToDto)
.collect(Collectors.toList());
}
@Transactional
public CustomerContainerResponseDto update(Long id, CustomerContainerRequestDto dto) {
CustomerContainer entity = customerContainerRepository.findById(id)
.orElseThrow(() -> new RuntimeException("CustomerContainer not found"));
updateInternal(entity, dto);
return mapToDto(entity);
}
public void delete(Long id) {
CustomerContainer entity = customerContainerRepository.findById(id)
.orElseThrow(() -> new RuntimeException("CustomerContainer not found"));
customerContainerRepository.delete(entity);
}
private void updateInternal(CustomerContainer entity, CustomerContainerRequestDto dto) {
if (dto.getCcoType() != null) entity.setCcoType(dto.getCcoType());
if (dto.getCcoCapacity() != null) entity.setCcoCapacity(dto.getCcoCapacity());
if (dto.getCcoOwnerType() != null) entity.setCcoOwnerType(dto.getCcoOwnerType());
if (dto.getCcoIsUsed() != null) entity.setCcoIsUsed(dto.getCcoIsUsed());
if (dto.getCcoHasLock() != null) entity.setCcoHasLock(dto.getCcoHasLock());
if (dto.getCcoHasWheel() != null) entity.setCcoHasWheel(dto.getCcoHasWheel());
if (dto.getCcoHasWoodframe() != null) entity.setCcoHasWoodframe(dto.getCcoHasWoodframe());
if (dto.getCcoStatus() != null) entity.setCcoStatus(dto.getCcoStatus());
}
private CustomerContainerResponseDto mapToDto(CustomerContainer entity) {
return CustomerContainerResponseDto.builder()
.ccoId(entity.getCcoId())
.ccoCustomerId(entity.getCcoCustomerId())
.ccoType(entity.getCcoType())
.ccoCapacity(entity.getCcoCapacity())
.ccoOwnerType(entity.getCcoOwnerType())
.ccoIsUsed(entity.getCcoIsUsed())
.ccoHasLock(entity.getCcoHasLock())
.ccoHasWheel(entity.getCcoHasWheel())
.ccoHasWoodframe(entity.getCcoHasWoodframe())
.ccoStatus(entity.getCcoStatus())
.build();
}
}

View File

@ -0,0 +1,100 @@
package com.goi.erp.service;
import com.goi.erp.dto.CustomerDailyInstallContainerRequestDto;
import com.goi.erp.dto.CustomerDailyInstallContainerResponseDto;
import com.goi.erp.entity.CustomerDailyInstallContainer;
import com.goi.erp.repository.CustomerDailyInstallContainerRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class CustomerDailyInstallContainerService {
private final CustomerDailyInstallContainerRepository repository;
public CustomerDailyInstallContainerResponseDto create(
CustomerDailyInstallContainerRequestDto dto
) {
CustomerDailyInstallContainer entity =
CustomerDailyInstallContainer.builder()
.cdicDailyInstallId(dto.getCdicDailyInstallId())
.cdicAction(dto.getCdicAction())
.cdicType(dto.getCdicType())
.cdicCapacity(dto.getCdicCapacity())
.cdicIsUsed(dto.getCdicIsUsed())
.cdicHasLock(dto.getCdicHasLock())
.cdicHasWheel(dto.getCdicHasWheel())
.cdicHasWoodframe(dto.getCdicHasWoodframe())
.cdicOwnerType(dto.getCdicOwnerType())
.build();
entity = repository.save(entity);
return mapToDto(entity);
}
public List<CustomerDailyInstallContainerResponseDto> getByDailyInstallId(
Long dailyInstallId
) {
return repository.findByCdicDailyInstallId(dailyInstallId)
.stream()
.map(this::mapToDto)
.collect(Collectors.toList());
}
@Transactional
public CustomerDailyInstallContainerResponseDto update(
Long id,
CustomerDailyInstallContainerRequestDto dto
) {
CustomerDailyInstallContainer entity = repository.findById(id)
.orElseThrow(() -> new RuntimeException("Container not found"));
updateInternal(entity, dto);
return mapToDto(entity);
}
public void delete(Long id) {
CustomerDailyInstallContainer entity = repository.findById(id)
.orElseThrow(() -> new RuntimeException("Container not found"));
repository.delete(entity);
}
private void updateInternal(
CustomerDailyInstallContainer entity,
CustomerDailyInstallContainerRequestDto dto
) {
if (dto.getCdicAction() != null) entity.setCdicAction(dto.getCdicAction());
if (dto.getCdicType() != null) entity.setCdicType(dto.getCdicType());
if (dto.getCdicCapacity() != null) entity.setCdicCapacity(dto.getCdicCapacity());
if (dto.getCdicIsUsed() != null) entity.setCdicIsUsed(dto.getCdicIsUsed());
}
private CustomerDailyInstallContainerResponseDto mapToDto(
CustomerDailyInstallContainer entity
) {
return CustomerDailyInstallContainerResponseDto.builder()
.cdicId(entity.getCdicId())
.cdicDailyInstallId(entity.getCdicDailyInstallId())
.cdicAction(entity.getCdicAction())
.cdicType(entity.getCdicType())
.cdicCapacity(entity.getCdicCapacity())
.cdicIsUsed(entity.getCdicIsUsed())
.build();
}
}

View File

@ -0,0 +1,96 @@
package com.goi.erp.service;
import com.goi.erp.dto.CustomerDailyInstallRequestDto;
import com.goi.erp.dto.CustomerDailyInstallResponseDto;
import com.goi.erp.entity.CustomerDailyInstall;
import com.goi.erp.repository.CustomerDailyInstallRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class CustomerDailyInstallService {
private final CustomerDailyInstallRepository repository;
public CustomerDailyInstallResponseDto create(CustomerDailyInstallRequestDto dto) {
CustomerDailyInstall entity = CustomerDailyInstall.builder()
.cdiOrderSeq(dto.getCdiOrderSeq())
.cdiDriverId(dto.getCdiDriverId())
.cdiInstallDate(dto.getCdiInstallDate())
.cdiInstallTime(dto.getCdiInstallTime())
.cdiCustomerId(dto.getCdiCustomerId())
.cdiAccountNo(dto.getCdiAccountNo())
.cdiCustomerName(dto.getCdiCustomerName())
.cdiPhone(dto.getCdiPhone())
.cdiAddress(dto.getCdiAddress())
.cdiCity(dto.getCdiCity())
.cdiPostalCode(dto.getCdiPostalCode())
.cdiGeoLat(dto.getCdiGeoLat())
.cdiGeoLon(dto.getCdiGeoLon())
.cdiWorkType(dto.getCdiWorkType())
.cdiStatus(dto.getCdiStatus())
.build();
entity = repository.save(entity);
return mapToDto(entity);
}
public List<CustomerDailyInstallResponseDto> getByInstallDate(LocalDate date) {
return repository.findByCdiInstallDate(date)
.stream()
.map(this::mapToDto)
.collect(Collectors.toList());
}
@Transactional
public CustomerDailyInstallResponseDto update(Long id, CustomerDailyInstallRequestDto dto) {
CustomerDailyInstall entity = repository.findById(id)
.orElseThrow(() -> new RuntimeException("CustomerDailyInstall not found"));
updateInternal(entity, dto);
return mapToDto(entity);
}
public void delete(Long id) {
CustomerDailyInstall entity = repository.findById(id)
.orElseThrow(() -> new RuntimeException("CustomerDailyInstall not found"));
repository.delete(entity);
}
private void updateInternal(CustomerDailyInstall entity, CustomerDailyInstallRequestDto dto) {
if (dto.getCdiDriverId() != null) entity.setCdiDriverId(dto.getCdiDriverId());
if (dto.getCdiInstallTime() != null) entity.setCdiInstallTime(dto.getCdiInstallTime());
if (dto.getCdiStatus() != null) entity.setCdiStatus(dto.getCdiStatus());
if (dto.getCdiWorkNote() != null) entity.setCdiWorkNote(dto.getCdiWorkNote());
}
private CustomerDailyInstallResponseDto mapToDto(CustomerDailyInstall entity) {
return CustomerDailyInstallResponseDto.builder()
.cdiUuid(entity.getCdiUuid())
.cdiOrderSeq(entity.getCdiOrderSeq())
.cdiDriverId(entity.getCdiDriverId())
.cdiInstallDate(entity.getCdiInstallDate())
.cdiInstallTime(entity.getCdiInstallTime())
.cdiCustomerId(entity.getCdiCustomerId())
.cdiCustomerName(entity.getCdiCustomerName())
.cdiStatus(entity.getCdiStatus())
.build();
}
}

View File

@ -44,8 +44,10 @@ public class CustomerDailyOrderService {
CustomerDailyOrder order = CustomerDailyOrder.builder()
.cdoUuid(UUID.randomUUID())
.cdoOrderDate(dto.getCdoOrderDate())
.cdoJobType(dto.getCdoJobType())
.cdoOrderType(dto.getCdoOrderType())
.cdoRequestNote(dto.getCdoRequestNote())
.cdoRegionId(dto.getCdoRegionId())
.cdoDriverId(driverId)
.cdoCustomerId(customerId)
.cdoCustomerNo(dto.getCdoCustomerNo())
@ -166,8 +168,10 @@ public class CustomerDailyOrderService {
Long driverId = resolveDriverId(dto);
// null 아닌 경우만 업데이트
if (dto.getCdoJobType() != null) order.setCdoJobType(dto.getCdoJobType());
if (dto.getCdoOrderType() != null) order.setCdoOrderType(dto.getCdoOrderType());
if (dto.getCdoRequestNote() != null) order.setCdoRequestNote(dto.getCdoRequestNote());
if (dto.getCdoRegionId() != null) order.setCdoRegionId(dto.getCdoRegionId());
if (dto.getCdoDriverId() != null || dto.getCdoExternalDriverId() != null || dto.getCdoDriverUuid() != null) order.setCdoDriverId(driverId);
if (dto.getCdoPaymentType() != null) order.setCdoPaymentType(dto.getCdoPaymentType());
if (dto.getCdoCycle() != null) order.setCdoCycle(dto.getCdoCycle());
@ -199,9 +203,11 @@ public class CustomerDailyOrderService {
return CustomerDailyOrderResponseDto.builder()
.cdoUuid(order.getCdoUuid())
.cdoOrderDate(order.getCdoOrderDate())
.cdoJobType(order.getCdoJobType())
.cdoOrderType(order.getCdoOrderType())
.cdoRequestNote(order.getCdoRequestNote())
// .cdoDriverId(order.getCdoDriverId())
.cdoRegionId(order.getCdoRegionId())
.cdoDriverId(order.getCdoDriverId())
.cdoCustomerNo(order.getCdoCustomerNo())
.cdoPaymentType(order.getCdoPaymentType())
.cdoCycle(order.getCdoCycle())

View File

@ -0,0 +1,97 @@
package com.goi.erp.service;
import com.goi.erp.dto.CustomerRegionRequestDto;
import com.goi.erp.dto.CustomerRegionResponseDto;
import com.goi.erp.entity.CustomerRegion;
import com.goi.erp.repository.CustomerRegionRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class CustomerRegionService {
private final CustomerRegionRepository customerRegionRepository;
/**
* CREATE
*/
public CustomerRegionResponseDto create(CustomerRegionRequestDto dto) {
CustomerRegion entity = CustomerRegion.builder()
.creName(dto.getCreName())
.creStatus(dto.getCreStatus())
.build();
entity = customerRegionRepository.save(entity);
return mapToDto(entity);
}
/**
* GET ALL
*/
public List<CustomerRegionResponseDto> getAll() {
return customerRegionRepository.findAll()
.stream()
.map(this::mapToDto)
.collect(Collectors.toList());
}
/**
* GET BY ID
*/
public CustomerRegionResponseDto getById(Long id) {
CustomerRegion entity = customerRegionRepository.findById(id)
.orElseThrow(() -> new RuntimeException("CustomerRegion not found"));
return mapToDto(entity);
}
/**
* UPDATE
*/
@Transactional
public CustomerRegionResponseDto update(Long id, CustomerRegionRequestDto dto) {
CustomerRegion entity = customerRegionRepository.findById(id)
.orElseThrow(() -> new RuntimeException("CustomerRegion not found"));
updateInternal(entity, dto);
return mapToDto(entity);
}
/**
* DELETE
*/
public void delete(Long id) {
CustomerRegion entity = customerRegionRepository.findById(id)
.orElseThrow(() -> new RuntimeException("CustomerRegion not found"));
customerRegionRepository.delete(entity);
}
private void updateInternal(CustomerRegion entity, CustomerRegionRequestDto dto) {
if (dto.getCreName() != null) entity.setCreName(dto.getCreName());
if (dto.getCreStatus() != null) entity.setCreStatus(dto.getCreStatus());
}
private CustomerRegionResponseDto mapToDto(CustomerRegion entity) {
return CustomerRegionResponseDto.builder()
.creId(entity.getCreId())
.creName(entity.getCreName())
.creStatus(entity.getCreStatus())
.build();
}
}