[2025-01-07] 添加 Linkwarden、集简云对接、Yearning部署指南
Some checks failed
Publish to Confluence / confluence (push) Failing after 2m42s

This commit is contained in:
liuxiaohua 2025-01-07 14:16:42 +08:00
parent 66cb01b7b1
commit ca283596b1
9 changed files with 3764 additions and 52 deletions

View File

@ -1,7 +1,17 @@
## 20250106 - 20250110
- [ ] 集简云对接
- 基础架子搭建
- 接口对接
## 20241230 - 20250103
- [X] 完成 yapi oidc 验证
- [ ] [YAPI-OIDC文档]()
1. - [X] 源码构建及错误处理
2. - [X] Docker镜像构建
3. - [X] OIDC 插件安装
4. - [X] [YApi部署指南](http://confluence.qifu.com/pages/viewpage.action?pageId=38507970)
- [X] JenkinsSSO [接入文档](http://confluence.qifu.com/pages/viewpage.action?pageId=38507984)
- [X] 面试
## 20241223 - 20241227

View File

@ -1,21 +0,0 @@
## YEARNING
### YEARNING 安装启动
可以参考https://next.yearning.io/zh/usage/ixah25xr/
```shell
```
### YEARNING OIDC 配置
可以参考https://next.yearning.io/zh/usage/boccobus/
```shell
```
## 参考
- [YAPI安装教程](https://blog.csdn.net/IT_ZRS/article/details/118642997)

View File

@ -0,0 +1,31 @@
<!-- Space: qifu -->
<!-- Parent: 后端技术&知识&规范 -->
<!-- Parent: 技术方案 -->
<!-- Parent: 基建 -->
<!-- Title: 20250104-Linkwarden部署指南 -->
<!-- Macro: :anchor\((.*)\):
Template: ac:anchor
Anchor: ${1} -->
<!-- Macro: \!\[.*\]\((.+)\)\<\!\-\- width=(.*) \-\-\>
Template: ac:image
Url: ${1}
Width: ${2} -->
<!-- Macro: \<\!\-\- :toc: \-\-\>
Template: ac:toc
Printable: 'false'
MinLevel: 2
MaxLevel: 4 -->
<!-- Include: 杂项/声明文件.md -->
<!-- :toc: -->
# Jenkins SAML 插件整合 Keycloak 配置指南
- [Self-Host安装](https://docs.linkwarden.app/self-hosting/installation)
- [SSO配置](https://docs.linkwarden.app/self-hosting/sso-oauth#keycloak)
## 参考
- [Linkwarden](https://docs.linkwarden.app/)

View File

@ -0,0 +1,237 @@
<!-- Space: qifu -->
<!-- Parent: 后端技术&知识&规范 -->
<!-- Parent: 技术方案 -->
<!-- Parent: 基建 -->
<!-- Title: 20250107-Yearning安装及SSO接入指南 -->
<!-- Macro: :anchor\((.*)\):
Template: ac:anchor
Anchor: ${1} -->
<!-- Macro: \!\[.*\]\((.+)\)\<\!\-\- width=(.*) \-\-\>
Template: ac:image
Url: ${1}
Width: ${2} -->
<!-- Macro: \<\!\-\- :toc: \-\-\>
Template: ac:toc
Printable: 'false'
MinLevel: 2
MaxLevel: 4 -->
<!-- Include: 杂项/声明文件.md -->
<!-- :toc: -->
# Yearning 安装及 SSO 接入指南
## Yearning 安装启动
可以参考https://next.yearning.io/zh/usage/ixah25xr/
### Docker Compose
#### `docker-compose.yml` 文件
```yaml
version: '3'
services:
yearning:
image: yeelabs/yearning:v3.1.5
environment:
MYSQL_USER: yearning
MYSQL_PASSWORD: ukC2ZkcG_ZTeb
MYSQL_ADDR: mysql
MYSQL_DB: yearning
SECRET_KEY: dbcjqheupqjsuwsm
IS_DOCKER: is_docker
ports:
- 8000:8000
volumes:
- ./opt/conf.toml:/opt/conf.toml
# 首次使用请先初始化
# command: /bin/bash -c "./Yearning install && ./Yearning run"
depends_on:
- mysql
restart: always
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: ukC2ZkcG_ZTeb
MYSQL_DATABASE: yearning
MYSQL_USER: yearning
MYSQL_PASSWORD: ukC2ZkcG_ZTeb
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_general_ci
volumes:
- ./data/mysql:/var/lib/mysql
# 默认账号admin默认密码Yearning_admin
```
#### `conf.toml` 文件
```java
[Mysql]
Db = "Yearning"
Host = "127.0.0.1"
Port = "3306"
Password = ""
User = "root"
[General]
SecretKey = "dbcjqheupqjsuwsm"
Hours = 4
Lang="zh_CN"
[Oidc]
Enable = false
ClientId = "${keycloak的客户端ID}"
ClientSecret = "${keycloak的客户端Secret}"
Scope = "openid profile"
AuthUrl = "${issuer链接}/protocol/openid-connect/auth"
TokenUrl = "${issuer链接}/protocol/openid-connect/token"
UserUrl = "${issuer链接}/protocol/openid-connect/userinfo"
RedirectUrL = "${yearning的地址}/oidc/_token-login"
UserNameKey = "preferred_username"
RealNameKey = "name"
EmailKey = "email"
SessionKey = "session_state"
```
### Yearning OIDC 配置
可以参考https://next.yearning.io/zh/usage/boccobus/
#### 修改 `conf.toml`Keycloak示例
```java
[Oidc]
Enable = true
ClientId = "${keycloak的客户端ID}"
ClientSecret = "${keycloak的客户端Secret}"
Scope = "openid profile"
AuthUrl = "${issuer链接}/protocol/openid-connect/auth"
TokenUrl = "${issuer链接}/protocol/openid-connect/token"
UserUrl = "${issuer链接}/protocol/openid-connect/userinfo"
RedirectUrL = "${yearning的地址}/oidc/_token-login"
UserNameKey = "preferred_username"
RealNameKey = "name"
EmailKey = "email"
SessionKey = "session_state"
```
- ${keycloak的客户端ID}:例如 `yearning`
- ${keycloak的客户端Secret}: Keycloak中获取
- ${issuer链接}: Keycloak 中获取
- ${yearning的地址}yearning 请求地址
### 异常处理
- 如果出现异常,可以排查 `Yearning` 服务和 `Keycloak` 服务是否可以访问通畅。
- 或者说 `Yearning` SSO 配置中的链接在 `Yearning` 所在服务中是否可以正常访问
## 本地构建启动(参考)
- Yearning `3.1.9.1`
- 系统 `Ubuntu24.04`
- nodejs `v18.20.5`
- npm `10.8.2`
- go `go version go1.22.10 linux/amd64`
### 安装 GO
#### 下载安装
- 下载 gohttps://go.dev/dl/
```shell
# 解压
tar -zxf go1.22.10.linux-amd64.tar.gz
# 移动
mv go /usr/local/go
# 配置环境变量
vi /etc/profile
####-/etc/profile start
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
####-/etc/profile end
# 使配置生效
source /etc/profile
# 查看是否成功
go version
```
#### 配置 go proxy
参考https://goproxy.cn/
```shell
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
```
### 安装 Node
#### 下载安装
- 下载 nodejshttps://nodejs.org/en/download/
```shell
# 解压
xz -d node-v18.20.5-linux-x64.tar.xz
tar tar -xf node-v18.20.5-linux-x64.tar
# 移动
mv node-v18.20.5-linux-x64 /usr/local/nodejs
# 配置环境变量
vi /etc/profile
####-/etc/profile start
export GOROOT=/usr/local/go
export NODE_HOME=/usr/local/nodejs
export PATH=$PATH:$GOROOT/bin:$NODE_HOME/bin
####-/etc/profile end
# 验证安装
node -v
npm -v
```
### Yearning 源码安装
- 工作目录: `/usr/local/workspace`
#### 获取 Yearning
```shell
git clone https://github.com/cookieY/Yearning.git
```
#### 获取 Yearning 前端
```shell
git clone https://github.com/cookieY/gemini-next.git
```
#### 编译前端代码
```shell
# 进入目录
cd /usr/local/workspace/gemini-next
#-安装
npm install --registry https://registry.npmmirror.com
#-构建
npm run build --registry https://registry.npmmirror.com
#- 将目标文件移动到源文件目录
mv dist /usr/local/workspace/Yearning/src/service/
```
#### 编译后端代码
```shell
cd /usr/local/workspace/Yearning
go mod tidy
cp conf.toml.template conf.toml
# 修改 配置文件
vi conf.toml
# 初始化(第一次需要)
# go run main.go install
# 启动
go run main.go run
```
- 启动报错chat/* xxx
- `vi src/service/yearning.go`
- 删除报错提示的行相关的代码
## 参考
- [Yearning安装教程](https://next.yearning.io/zh/usage/ptbzchak/)
- [使用go语言编译部署最新版Yearning【v3.0.1】](https://blog.csdn.net/qq_44930876/article/details/125679454)

View File

@ -0,0 +1,102 @@
<!-- Space: qifu -->
<!-- Parent: 后端技术&知识&规范 -->
<!-- Parent: 技术方案 -->
<!-- Parent: 基建 -->
<!-- Title: 20250106-集简云对接方案 -->
<!-- Macro: :anchor\((.*)\):
Template: ac:anchor
Anchor: ${1} -->
<!-- Macro: \!\[.*\]\((.+)\)\<\!\-\- width=(.*) \-\-\>
Template: ac:image
Url: ${1}
Width: ${2} -->
<!-- Macro: \<\!\-\- :toc: \-\-\>
Template: ac:toc
Printable: 'false'
MinLevel: 2
MaxLevel: 4 -->
<!-- Include: 杂项/声明文件.md -->
<!-- :toc: -->
# 集简云对接方案
## 一、现状
### 业务背景
需要对接和拉取ERP和电商平台订单
## 二、需求
### 业务需求
需要对接和拉取ERP和电商平台订单
## 三、设计目标
### 实现的功能
- ERP订单拉取
- 领星ERP
- 聚水潭
- 易仓
- 马帮
- 电商平台订单拉取
- Amazon
- Tiktok
- Ebay
- Shopee
- Lazada
## 四、整体设计
### 整体架构
![](https://picture.texous.cn/blog/20250106142814939.png)
### 交互流程
#### 应用授权流程
![](https://picture.texous.cn/blog/20250106145111478.png)
#### 订单拉取流程
![](https://picture.texous.cn/blog/20250106152557525.png)
## 五、详细设计
### 功能模块设计
### 潜在风险
- 订单信息回传暂时没找到渠道
- 集简云对接需要付费
## 六、工作量和排期
### 开发时间
### 联调时间
### 提测时间
### 上线时间
## 七、设计评审意见
## 八、参考文档
- [Okta](https://www.okta.com/)
- [CAS 单点登录部署](https://blog.csdn.net/xu_guo_jie/article/details/104209452)
- [集成文档参考](https://docs.authing.cn/v2/integration/?category=all&page=2)
- [CAS Server](https://github.com/apereo/cas)
- [CAS 整合 LDAP](https://www.doc88.com/p-0774845211878.html)
- [CAS](https://zhuanlan.zhihu.com/p/610470663)
- [OIDC](https://zhuanlan.zhihu.com/p/539297736)
- [LDAP](https://zhuanlan.zhihu.com/p/608437013)
- [IAM单点登录之CAS协议分析](https://zhuanlan.zhihu.com/p/627920220)
- [Keycloak](https://www.keycloak.org/)
- [Keycloak OIDC](https://www.keycloak.org/securing-apps/oidc-layers)
- [Keycloak 默认 Provider 配置](https://www.keycloak.org/docs/latest/server_admin/index.html#default_identity_provider)
- [Keycloak custom theme](https://springdoc.cn/spring-keycloak-custom-themes/)
- [Keycloak custom theme](https://blog.csdn.net/q1ngqingsky/article/details/123417611)

15
杂项/20250106-备忘.md Normal file
View File

@ -0,0 +1,15 @@
## 集简云
- corp_id: 3GUjL9MIoBYYXJetxI0wEUdmvbk1K6Le
- secret: tY1XBKjjzZQXkyZXply35hL36dTFJzI7
### APP 相关
| APP | APP_KEY | ACTION | ACTION_KEY |
|-------|---------|-----------|------------|
| 领星ERP | 1001686 | 查询亚马逊店铺信息 | 1008458 |
| | | 查询亚马逊订单列表 | 1008460 |
| | | 查询亚马逊订单详情 | 1008461 |
| 聚水潭 | 1000215 | 查询店铺列表 | 1015873 |
| | | 查询订单列表 | 1015869 |
| | | 查询店铺列表 | 1015873 |

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/25.0.2 Chrome/128.0.6613.186 Electron/32.2.5 Safari/537.36" version="25.0.2">
<diagram id="23iRSUPoRavnBvh4doch" name="Page-1">
<mxGraphModel dx="1562" dy="1037" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="RBETg45X8NGVP7TbEJGc-1" value="企赋网关应用授权流程" style="swimlane;html=1;childLayout=stackLayout;resizeParent=1;resizeParentMax=0;startSize=20;whiteSpace=wrap;" vertex="1" parent="1">
<mxGeometry x="80" y="160" width="490" height="550" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-2" value="业务中台" style="swimlane;html=1;startSize=20;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-1">
<mxGeometry y="20" width="120" height="530" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-2" source="RBETg45X8NGVP7TbEJGc-5" target="RBETg45X8NGVP7TbEJGc-7">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-5" value="授权" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-2">
<mxGeometry x="20" y="40" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-7" value="输入&lt;div&gt;授权信息&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-2">
<mxGeometry x="20" y="110" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-18" value="完成授权" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-2">
<mxGeometry x="20" y="470" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-3" value="企赋网关" style="swimlane;html=1;startSize=20;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-1">
<mxGeometry x="120" y="20" width="250" height="530" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-3" source="RBETg45X8NGVP7TbEJGc-8" target="RBETg45X8NGVP7TbEJGc-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-8" value="获取corp_oken" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="20" y="110" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-9" value="请求开通企业" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="150" y="190" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-3" source="RBETg45X8NGVP7TbEJGc-10" target="RBETg45X8NGVP7TbEJGc-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-23" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="RBETg45X8NGVP7TbEJGc-22">
<mxGeometry x="-0.1809" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-3" source="RBETg45X8NGVP7TbEJGc-10" target="RBETg45X8NGVP7TbEJGc-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-27" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="RBETg45X8NGVP7TbEJGc-26">
<mxGeometry x="-0.1353" relative="1" as="geometry">
<mxPoint y="-14" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-10" value="&lt;span style=&quot;background-color: initial;&quot;&gt;企业&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;存在&lt;/span&gt;&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="35" y="180" width="50" height="60" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-3" source="RBETg45X8NGVP7TbEJGc-12" target="RBETg45X8NGVP7TbEJGc-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-12" value="存储企业信息" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="150" y="260" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-3" source="RBETg45X8NGVP7TbEJGc-13" target="RBETg45X8NGVP7TbEJGc-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-29" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="RBETg45X8NGVP7TbEJGc-28">
<mxGeometry x="-0.0536" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-3" source="RBETg45X8NGVP7TbEJGc-13" target="RBETg45X8NGVP7TbEJGc-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-33" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="RBETg45X8NGVP7TbEJGc-32">
<mxGeometry x="-0.2008" relative="1" as="geometry">
<mxPoint y="-16" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-13" value="&lt;span style=&quot;background-color: initial;&quot;&gt;应用&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;存在&lt;/span&gt;&lt;/div&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="35" y="320" width="50" height="60" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-14" value="请求添加应用" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="150" y="330" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-3" source="RBETg45X8NGVP7TbEJGc-16" target="RBETg45X8NGVP7TbEJGc-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-16" value="存储应用信息" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="150" y="400" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-17" value="完成授权" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-3">
<mxGeometry x="20" y="470" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-4" value="集简云" style="swimlane;html=1;startSize=20;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-1">
<mxGeometry x="370" y="20" width="120" height="530" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-11" value="开通企业" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-4">
<mxGeometry x="20" y="190" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-15" value="添加应用" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-4">
<mxGeometry x="20" y="330" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-37" value="获取corp_token" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="RBETg45X8NGVP7TbEJGc-4">
<mxGeometry x="20" y="110" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-1" source="RBETg45X8NGVP7TbEJGc-7" target="RBETg45X8NGVP7TbEJGc-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-1" source="RBETg45X8NGVP7TbEJGc-9" target="RBETg45X8NGVP7TbEJGc-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-1" source="RBETg45X8NGVP7TbEJGc-11" target="RBETg45X8NGVP7TbEJGc-12">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="430" y="300" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-1" source="RBETg45X8NGVP7TbEJGc-14" target="RBETg45X8NGVP7TbEJGc-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-1" source="RBETg45X8NGVP7TbEJGc-15" target="RBETg45X8NGVP7TbEJGc-16">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="430" y="440" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-1" source="RBETg45X8NGVP7TbEJGc-17" target="RBETg45X8NGVP7TbEJGc-18">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="RBETg45X8NGVP7TbEJGc-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="RBETg45X8NGVP7TbEJGc-1" source="RBETg45X8NGVP7TbEJGc-8" target="RBETg45X8NGVP7TbEJGc-37">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>