From: Snapshot-Content-Location: https://docs.google.com/document/u/0/d/1LMjIhp2TCy9QpzTUzL55cP0dx61WM4epmr8qy9N9Rgc/mobilebasic?hl=th-TH&pli=1 Subject: LCBP3-DMS Requirements Specification (v2.0) Date: Thu, 16 Oct 2025 22:57:30 +0700 MIME-Version: 1.0 Content-Type: multipart/related; type="text/html"; boundary="----MultipartBoundary--zmGvipyjWUpT0gAfLJbw3hmbaeNqVxyLAosKXVU9r0----" ------MultipartBoundary--zmGvipyjWUpT0gAfLJbw3hmbaeNqVxyLAosKXVU9r0---- Content-Type: text/html Content-ID: Content-Transfer-Encoding: binary Content-Location: https://docs.google.com/document/u/0/d/1LMjIhp2TCy9QpzTUzL55cP0dx61WM4epmr8qy9N9Rgc/mobilebasic?hl=th-TH&pli=1 LCBP3-DMS Requirements Specification (v2.0)
LCBP3-DMS Requirements Specification (v2.0)

LCBP3-DMS: Requirements Specification (v2.0)

เอกสารนี้สรุปข้อกำหนดทางธุรกิจ, สถาปัตยกรรมทางเทคนิค, และรายละเอียดการ υλοποίηση (Implementation) สำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System)

1. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)

ระบบใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา

  • 1.1 Infrastructure & Environment:
  • Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
  • Containerization: Docker & Docker Compose
  • Development Environment: VS Code on Windows 11
  • Domain: np-dms.work (มี Fixed IP)
  • Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
  • 1.2 Code Hosting:
  • Service: Gitea (Self-hosted on QNAP)
  • Domain: git.np-dms.work
  • หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
  • 1.3 Backend / Data Platform:
  • Framework: NestJS (Node.js, TypeScript, ESM)
  • Domain: backend.np-dms.work
  • หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
  • 1.4 Database:
  • Service: MariaDB
  • หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
  • Tooling: DBeaver (Community Edition) สำหรับการออกแบบและจัดการฐานข้อมูล
  • 1.5 Frontend:
  • Framework: Next.js (App Router, React, TypeScript, ESM)
  • Styling: Tailwind CSS + PostCSS
  • Component Library: shadcn/ui
  • Domain: lcbp3.np-dms.work
  • หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
  • 1.6 Reverse Proxy:
  • Service: Nginx Proxy Manager
  • หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ

2. ข้อกำหนดด้านฟังก์ชันการทำงาน (Functional Requirements)

2.1 การจัดการโครงสร้างโครงการและองค์กร

  • 2.1.1 โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
  • 2.1.2 สัญญา (Contracts): ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
  • 2.1.3 องค์กร (Organizations):
  • มีหลายองค์กรในโครงการ บางองค์กรเช่น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
  • Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น

2.2 การจัดการเอกสาร (Correspondence Management)

  • 2.2.1 ประเภทเอกสาร: ระบบต้องรองรับเอกสารหลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
  • 2.2.2 การสร้างเอกสาร:
  • ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ "ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
  • เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
  • 2.2.3 การอ้างอิงและจัดกลุ่ม:
  • เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
  • สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
  • 2.2.4 ประวัติการแก้ไข (Revisions): เอกสารสามารถมีได้หลาย Revision โดยระบบจะเก็บประวัติการแก้ไขทั้งหมด
  • 2.2.5 การจัดเก็บ: เอกสารและไฟล์แนบจะถูกจัดเก็บในโฟลเดอร์บน Server โดยมีการอ้างอิงข้อมูล (Metadata) ในฐานข้อมูล และสามารถจัดเรียงตามวันที่ออกเอกสาร (Issue Date) ได้

2.3 การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow)

  • 2.3.1 ประเภท: เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะคือต้องได้รับการอนุมัติ และมีประเภทดังนี้:
  • Request for Material Approval (RFA_Mat)
  • Request for Method statement Approval (RFA_MST)
  • Request for Document Approval (RFA_DOC)
  • Request for Drawing Approval (RFA_DWG)
  • 2.3.2 Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น ส่งจาก Originator -> Org1 -> Org2 -> Org3 แล้วส่งผลกลับตามลำดับเดิม
  • 2.3.3 การจัดการ Drawing (RFA_DWG):
  • เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (Shp_DWG) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
  • Shop Drawing สามารถอ้างอิงถึง Contract Drawing (Con_DWG) หลายแผ่น หรือไม่อ้างถึงก็ได้
  • ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน

2.4 ใบเวียนเอกสารภายใน (Internal Circulation Sheet)

  • 2.4.1 วัตถุประสงค์: การสื่อสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
  • 2.4.2 การระบุผู้รับผิดชอบ:
  • ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
  • ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
  • ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
  • 2.4.3 การติดตามงาน:
  • สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
  • มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
  • สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว

3. ข้อกำหนดด้านสิทธิ์และการเข้าถึง (Access Control Requirements)

  • 3.1 ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
  • 3.2 ระดับของสิทธิ์:
  • Global Roles: สิทธิ์ในภาพรวมของระบบ
  • Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
  • 3.3 บทบาท (Roles) พื้นฐาน:
  • Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กร
  • Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรได้
  • Document Control / Editor: สามารถ เพิ่ม/แก้ไข เอกสาร เฉพาะในองค์กรที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
  • สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin Panel
  • 3.4 การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ

4. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)

  • 4.1 Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
  • Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
  • Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
  • Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
  • 4.2 หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
  • 4.3 หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
  • การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
  • ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
  • 4.4 การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
  • 4.5 การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้

5. ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)

  • 5.1 การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
  • 5.2 การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสารจากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
  • 5.3 การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
  • 5.4 ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
  • 5.5 ความปลอดภัย (Security):
  • มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
  • การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด

------MultipartBoundary--zmGvipyjWUpT0gAfLJbw3hmbaeNqVxyLAosKXVU9r0---- Content-Type: text/css Content-Transfer-Encoding: binary Content-Location: cid:css-941c3c4b-eff7-4021-b2a8-f5f59715b21d@mhtml.blink @charset "utf-8"; .lst-kix_list_14-1 > li::before { content: "○ "; } .lst-kix_list_14-3 > li::before { content: "■ "; } .lst-kix_list_14-0 > li::before { content: "● "; } .lst-kix_list_14-4 > li::before { content: "■ "; } .lst-kix_list_14-5 > li::before { content: "■ "; } .lst-kix_list_14-7 > li::before { content: "■ "; } .lst-kix_list_14-6 > li::before { content: "■ "; } ul.lst-kix_list_9-3 { list-style-type: none; } ul.lst-kix_list_9-4 { list-style-type: none; } ul.lst-kix_list_9-1 { list-style-type: none; } ul.lst-kix_list_9-2 { list-style-type: none; } ul.lst-kix_list_9-7 { list-style-type: none; } ul.lst-kix_list_9-8 { list-style-type: none; } ul.lst-kix_list_9-5 { list-style-type: none; } ul.lst-kix_list_9-6 { list-style-type: none; } ul.lst-kix_list_9-0 { list-style-type: none; } .lst-kix_list_14-2 > li::before { content: "■ "; } ul.lst-kix_list_17-1 { list-style-type: none; } ul.lst-kix_list_17-0 { list-style-type: none; } ul.lst-kix_list_17-8 { list-style-type: none; } ul.lst-kix_list_17-7 { list-style-type: none; } ul.lst-kix_list_17-6 { list-style-type: none; } ul.lst-kix_list_17-5 { list-style-type: none; } ul.lst-kix_list_17-4 { list-style-type: none; } ul.lst-kix_list_17-3 { list-style-type: none; } .lst-kix_list_14-8 > li::before { content: "■ "; } ul.lst-kix_list_17-2 { list-style-type: none; } .lst-kix_list_5-0 > li::before { content: "● "; } .lst-kix_list_5-3 > li::before { content: "■ "; } .lst-kix_list_5-2 > li::before { content: "■ "; } .lst-kix_list_5-1 > li::before { content: "○ "; } .lst-kix_list_5-7 > li::before { content: "■ "; } ul.lst-kix_list_8-4 { list-style-type: none; } ul.lst-kix_list_8-5 { list-style-type: none; } .lst-kix_list_5-6 > li::before { content: "■ "; } .lst-kix_list_5-8 > li::before { content: "■ "; } ul.lst-kix_list_8-2 { list-style-type: none; } ul.lst-kix_list_8-3 { list-style-type: none; } ul.lst-kix_list_8-8 { list-style-type: none; } ul.lst-kix_list_8-6 { list-style-type: none; } ul.lst-kix_list_8-7 { list-style-type: none; } .lst-kix_list_5-4 > li::before { content: "■ "; } .lst-kix_list_5-5 > li::before { content: "■ "; } ul.lst-kix_list_8-0 { list-style-type: none; } ul.lst-kix_list_8-1 { list-style-type: none; } .lst-kix_list_6-1 > li::before { content: "○ "; } .lst-kix_list_6-3 > li::before { content: "■ "; } .lst-kix_list_6-0 > li::before { content: "● "; } .lst-kix_list_6-4 > li::before { content: "■ "; } ul.lst-kix_list_16-2 { list-style-type: none; } ul.lst-kix_list_16-1 { list-style-type: none; } ul.lst-kix_list_16-0 { list-style-type: none; } .lst-kix_list_6-2 > li::before { content: "■ "; } ul.lst-kix_list_16-8 { list-style-type: none; } ul.lst-kix_list_16-7 { list-style-type: none; } ul.lst-kix_list_16-6 { list-style-type: none; } ul.lst-kix_list_16-5 { list-style-type: none; } ul.lst-kix_list_16-4 { list-style-type: none; } .lst-kix_list_6-8 > li::before { content: "■ "; } ul.lst-kix_list_16-3 { list-style-type: none; } .lst-kix_list_6-5 > li::before { content: "■ "; } .lst-kix_list_6-7 > li::before { content: "■ "; } .lst-kix_list_6-6 > li::before { content: "■ "; } .lst-kix_list_7-4 > li::before { content: "■ "; } .lst-kix_list_7-6 > li::before { content: "■ "; } .lst-kix_list_7-2 > li::before { content: "■ "; } .lst-kix_list_13-7 > li::before { content: "■ "; } .lst-kix_list_7-8 > li::before { content: "■ "; } .lst-kix_list_15-5 > li::before { content: "■ "; } .lst-kix_list_4-1 > li::before { content: "○ "; } .lst-kix_list_15-7 > li::before { content: "■ "; } ul.lst-kix_list_19-7 { list-style-type: none; } ul.lst-kix_list_19-6 { list-style-type: none; } .lst-kix_list_4-3 > li::before { content: "■ "; } .lst-kix_list_4-5 > li::before { content: "■ "; } ul.lst-kix_list_19-5 { list-style-type: none; } ul.lst-kix_list_19-4 { list-style-type: none; } ul.lst-kix_list_19-3 { list-style-type: none; } ul.lst-kix_list_19-2 { list-style-type: none; } ul.lst-kix_list_19-1 { list-style-type: none; } ul.lst-kix_list_19-0 { list-style-type: none; } .lst-kix_list_15-1 > li::before { content: "○ "; } .lst-kix_list_15-3 > li::before { content: "■ "; } ul.lst-kix_list_19-8 { list-style-type: none; } .lst-kix_list_12-3 > li::before { content: "■ "; } .lst-kix_list_12-1 > li::before { content: "○ "; } .lst-kix_list_13-3 > li::before { content: "■ "; } ul.lst-kix_list_18-0 { list-style-type: none; } .lst-kix_list_13-5 > li::before { content: "■ "; } .lst-kix_list_12-5 > li::before { content: "■ "; } ul.lst-kix_list_18-8 { list-style-type: none; } ul.lst-kix_list_18-7 { list-style-type: none; } ul.lst-kix_list_18-6 { list-style-type: none; } ul.lst-kix_list_18-5 { list-style-type: none; } .lst-kix_list_12-7 > li::before { content: "■ "; } ul.lst-kix_list_18-4 { list-style-type: none; } ul.lst-kix_list_18-3 { list-style-type: none; } ul.lst-kix_list_18-2 { list-style-type: none; } ul.lst-kix_list_18-1 { list-style-type: none; } .lst-kix_list_13-1 > li::before { content: "○ "; } ul.lst-kix_list_f-7 { list-style-type: none; } ul.lst-kix_list_f-6 { list-style-type: none; } ul.lst-kix_list_f-5 { list-style-type: none; } ul.lst-kix_list_f-4 { list-style-type: none; } ul.lst-kix_list_f-8 { list-style-type: none; } ul.lst-kix_list_f-3 { list-style-type: none; } .lst-kix_list_3-0 > li::before { content: "● "; } ul.lst-kix_list_f-2 { list-style-type: none; } ul.lst-kix_list_f-1 { list-style-type: none; } ul.lst-kix_list_f-0 { list-style-type: none; } ul.lst-kix_list_5-7 { list-style-type: none; } ul.lst-kix_list_5-8 { list-style-type: none; } ul.lst-kix_list_5-5 { list-style-type: none; } ul.lst-kix_list_5-6 { list-style-type: none; } ul.lst-kix_list_5-0 { list-style-type: none; } .lst-kix_list_3-4 > li::before { content: "■ "; } ul.lst-kix_list_5-3 { list-style-type: none; } .lst-kix_list_3-3 > li::before { content: "■ "; } ul.lst-kix_list_5-4 { list-style-type: none; } ul.lst-kix_list_5-1 { list-style-type: none; } .lst-kix_list_8-0 > li::before { content: "● "; } ul.lst-kix_list_5-2 { list-style-type: none; } .lst-kix_list_8-7 > li::before { content: "■ "; } .lst-kix_list_3-8 > li::before { content: "■ "; } .lst-kix_list_f-6 > li::before { content: "■ "; } .lst-kix_list_a-7 > li::before { content: "■ "; } .lst-kix_list_f-7 > li::before { content: "■ "; } .lst-kix_list_8-3 > li::before { content: "■ "; } ul.lst-kix_list_13-5 { list-style-type: none; } ul.lst-kix_list_13-4 { list-style-type: none; } ul.lst-kix_list_13-3 { list-style-type: none; } ul.lst-kix_list_13-2 { list-style-type: none; } ul.lst-kix_list_13-1 { list-style-type: none; } .lst-kix_list_3-7 > li::before { content: "■ "; } ul.lst-kix_list_13-0 { list-style-type: none; } .lst-kix_list_8-4 > li::before { content: "■ "; } .lst-kix_list_a-2 > li::before { content: "■ "; } ul.lst-kix_list_13-8 { list-style-type: none; } .lst-kix_list_a-3 > li::before { content: "■ "; } .lst-kix_list_11-1 > li::before { content: "○ "; } ul.lst-kix_list_13-7 { list-style-type: none; } ul.lst-kix_list_13-6 { list-style-type: none; } .lst-kix_list_f-3 > li::before { content: "■ "; } .lst-kix_list_a-6 > li::before { content: "■ "; } .lst-kix_list_f-2 > li::before { content: "■ "; } .lst-kix_list_11-0 > li::before { content: "● "; } .lst-kix_list_8-8 > li::before { content: "■ "; } ul.lst-kix_list_e-8 { list-style-type: none; } .lst-kix_list_16-8 > li::before { content: "■ "; } ul.lst-kix_list_e-7 { list-style-type: none; } ul.lst-kix_list_e-6 { list-style-type: none; } .lst-kix_list_16-7 > li::before { content: "■ "; } ul.lst-kix_list_e-5 { list-style-type: none; } .lst-kix_list_e-3 > li::before { content: "■ "; } .lst-kix_list_e-7 > li::before { content: "■ "; } .lst-kix_list_e-2 > li::before { content: "■ "; } .lst-kix_list_e-6 > li::before { content: "■ "; } .lst-kix_list_4-8 > li::before { content: "■ "; } ul.lst-kix_list_e-0 { list-style-type: none; } .lst-kix_list_4-7 > li::before { content: "■ "; } .lst-kix_list_17-0 > li::before { content: "● "; } ul.lst-kix_list_e-4 { list-style-type: none; } ul.lst-kix_list_e-3 { list-style-type: none; } ul.lst-kix_list_e-2 { list-style-type: none; } ul.lst-kix_list_e-1 { list-style-type: none; } ul.lst-kix_list_4-8 { list-style-type: none; } .lst-kix_list_16-0 > li::before { content: "● "; } ul.lst-kix_list_4-6 { list-style-type: none; } ul.lst-kix_list_4-7 { list-style-type: none; } ul.lst-kix_list_4-0 { list-style-type: none; } .lst-kix_list_16-4 > li::before { content: "■ "; } ul.lst-kix_list_4-1 { list-style-type: none; } .lst-kix_list_16-3 > li::before { content: "■ "; } ul.lst-kix_list_4-4 { list-style-type: none; } ul.lst-kix_list_4-5 { list-style-type: none; } ul.lst-kix_list_4-2 { list-style-type: none; } ul.lst-kix_list_4-3 { list-style-type: none; } ul.lst-kix_list_12-6 { list-style-type: none; } ul.lst-kix_list_12-5 { list-style-type: none; } .lst-kix_list_17-7 > li::before { content: "■ "; } ul.lst-kix_list_12-4 { list-style-type: none; } ul.lst-kix_list_12-3 { list-style-type: none; } ul.lst-kix_list_12-2 { list-style-type: none; } ul.lst-kix_list_12-1 { list-style-type: none; } .lst-kix_list_17-8 > li::before { content: "■ "; } ul.lst-kix_list_12-0 { list-style-type: none; } .lst-kix_list_17-3 > li::before { content: "■ "; } .lst-kix_list_17-4 > li::before { content: "■ "; } ul.lst-kix_list_12-8 { list-style-type: none; } ul.lst-kix_list_12-7 { list-style-type: none; } .lst-kix_list_7-0 > li::before { content: "● "; } .lst-kix_list_2-4 > li::before { content: "■ "; } .lst-kix_list_2-8 > li::before { content: "■ "; } .lst-kix_list_7-3 > li::before { content: "■ "; } ul.lst-kix_list_7-5 { list-style-type: none; } .lst-kix_list_10-0 > li::before { content: "● "; } ul.lst-kix_list_7-6 { list-style-type: none; } ul.lst-kix_list_7-3 { list-style-type: none; } ul.lst-kix_list_7-4 { list-style-type: none; } .lst-kix_list_13-8 > li::before { content: "■ "; } .lst-kix_list_b-3 > li::before { content: "■ "; } .lst-kix_list_b-7 > li::before { content: "■ "; } .lst-kix_list_18-3 > li::before { content: "■ "; } .lst-kix_list_18-7 > li::before { content: "■ "; } ul.lst-kix_list_7-7 { list-style-type: none; } ul.lst-kix_list_7-8 { list-style-type: none; } ul.lst-kix_list_7-1 { list-style-type: none; } ul.lst-kix_list_7-2 { list-style-type: none; } ul.lst-kix_list_7-0 { list-style-type: none; } .lst-kix_list_7-7 > li::before { content: "■ "; } .lst-kix_list_15-4 > li::before { content: "■ "; } .lst-kix_list_10-4 > li::before { content: "■ "; } .lst-kix_list_10-8 > li::before { content: "■ "; } .lst-kix_list_4-0 > li::before { content: "● "; } ul.lst-kix_list_15-3 { list-style-type: none; } ul.lst-kix_list_15-2 { list-style-type: none; } .lst-kix_list_15-0 > li::before { content: "● "; } ul.lst-kix_list_15-1 { list-style-type: none; } .lst-kix_list_15-8 > li::before { content: "■ "; } ul.lst-kix_list_15-0 { list-style-type: none; } .lst-kix_list_4-4 > li::before { content: "■ "; } ul.lst-kix_list_15-8 { list-style-type: none; } ul.lst-kix_list_15-7 { list-style-type: none; } ul.lst-kix_list_15-6 { list-style-type: none; } .lst-kix_list_9-3 > li::before { content: "■ "; } ul.lst-kix_list_15-5 { list-style-type: none; } ul.lst-kix_list_15-4 { list-style-type: none; } .lst-kix_list_9-7 > li::before { content: "■ "; } .lst-kix_list_11-4 > li::before { content: "■ "; } .lst-kix_list_12-4 > li::before { content: "■ "; } ul.lst-kix_list_6-6 { list-style-type: none; } ul.lst-kix_list_6-7 { list-style-type: none; } ul.lst-kix_list_6-4 { list-style-type: none; } ul.lst-kix_list_6-5 { list-style-type: none; } ul.lst-kix_list_6-8 { list-style-type: none; } .lst-kix_list_1-0 > li::before { content: "● "; } .lst-kix_list_1a-3 > li::before { content: "■ "; } ul.lst-kix_list_6-2 { list-style-type: none; } .lst-kix_list_11-8 > li::before { content: "■ "; } ul.lst-kix_list_6-3 { list-style-type: none; } ul.lst-kix_list_6-0 { list-style-type: none; } .lst-kix_list_12-0 > li::before { content: "● "; } ul.lst-kix_list_6-1 { list-style-type: none; } .lst-kix_list_1-4 > li::before { content: "■ "; } .lst-kix_list_13-0 > li::before { content: "● "; } ul.lst-kix_list_14-4 { list-style-type: none; } ul.lst-kix_list_14-3 { list-style-type: none; } ul.lst-kix_list_14-2 { list-style-type: none; } .lst-kix_list_13-4 > li::before { content: "■ "; } ul.lst-kix_list_14-1 { list-style-type: none; } ul.lst-kix_list_14-0 { list-style-type: none; } ul.lst-kix_list_14-8 { list-style-type: none; } ul.lst-kix_list_14-7 { list-style-type: none; } .lst-kix_list_2-0 > li::before { content: "● "; } ul.lst-kix_list_14-6 { list-style-type: none; } ul.lst-kix_list_14-5 { list-style-type: none; } .lst-kix_list_1-8 > li::before { content: "■ "; } .lst-kix_list_12-8 > li::before { content: "■ "; } .lst-kix_list_c-0 > li::before { content: "● "; } .lst-kix_list_19-0 > li::before { content: "● "; } .lst-kix_list_19-1 > li::before { content: "○ "; } ul.lst-kix_list_b-8 { list-style-type: none; } ul.lst-kix_list_1-0 { list-style-type: none; } .lst-kix_list_c-1 > li::before { content: "○ "; } ul.lst-kix_list_b-3 { list-style-type: none; } ul.lst-kix_list_b-2 { list-style-type: none; } .lst-kix_list_c-3 > li::before { content: "■ "; } .lst-kix_list_c-4 > li::before { content: "■ "; } .lst-kix_list_19-4 > li::before { content: "■ "; } ul.lst-kix_list_b-1 { list-style-type: none; } ul.lst-kix_list_b-0 { list-style-type: none; } ul.lst-kix_list_b-7 { list-style-type: none; } ul.lst-kix_list_b-6 { list-style-type: none; } .lst-kix_list_c-2 > li::before { content: "■ "; } .lst-kix_list_19-2 > li::before { content: "■ "; } .lst-kix_list_19-3 > li::before { content: "■ "; } ul.lst-kix_list_b-5 { list-style-type: none; } ul.lst-kix_list_b-4 { list-style-type: none; } ul.lst-kix_list_1-3 { list-style-type: none; } ul.lst-kix_list_1-4 { list-style-type: none; } ul.lst-kix_list_1-1 { list-style-type: none; } ul.lst-kix_list_1-2 { list-style-type: none; } ul.lst-kix_list_1-7 { list-style-type: none; } ul.lst-kix_list_1-8 { list-style-type: none; } ul.lst-kix_list_1-5 { list-style-type: none; } ul.lst-kix_list_1-6 { list-style-type: none; } .lst-kix_list_1a-5 > li::before { content: "■ "; } .lst-kix_list_1a-6 > li::before { content: "■ "; } .lst-kix_list_1a-8 > li::before { content: "■ "; } .lst-kix_list_19-8 > li::before { content: "■ "; } .lst-kix_list_1a-7 > li::before { content: "■ "; } .lst-kix_list_19-5 > li::before { content: "■ "; } .lst-kix_list_19-6 > li::before { content: "■ "; } .lst-kix_list_19-7 > li::before { content: "■ "; } ul.lst-kix_list_a-4 { list-style-type: none; } ul.lst-kix_list_a-3 { list-style-type: none; } ul.lst-kix_list_a-2 { list-style-type: none; } ul.lst-kix_list_a-1 { list-style-type: none; } ul.lst-kix_list_a-8 { list-style-type: none; } ul.lst-kix_list_a-7 { list-style-type: none; } ul.lst-kix_list_a-6 { list-style-type: none; } ul.lst-kix_list_a-5 { list-style-type: none; } .lst-kix_list_d-6 > li::before { content: "■ "; } .lst-kix_list_d-8 > li::before { content: "■ "; } .lst-kix_list_d-7 > li::before { content: "■ "; } .lst-kix_list_d-2 > li::before { content: "■ "; } .lst-kix_list_18-0 > li::before { content: "● "; } .lst-kix_list_d-1 > li::before { content: "○ "; } .lst-kix_list_d-5 > li::before { content: "■ "; } .lst-kix_list_18-1 > li::before { content: "○ "; } .lst-kix_list_18-2 > li::before { content: "■ "; } .lst-kix_list_d-4 > li::before { content: "■ "; } .lst-kix_list_d-3 > li::before { content: "■ "; } .lst-kix_list_c-7 > li::before { content: "■ "; } ul.lst-kix_list_a-0 { list-style-type: none; } .lst-kix_list_c-5 > li::before { content: "■ "; } .lst-kix_list_c-8 > li::before { content: "■ "; } .lst-kix_list_d-0 > li::before { content: "● "; } .lst-kix_list_c-6 > li::before { content: "■ "; } .lst-kix_list_2-7 > li::before { content: "■ "; } ul.lst-kix_list_d-8 { list-style-type: none; } ul.lst-kix_list_d-7 { list-style-type: none; } ul.lst-kix_list_d-6 { list-style-type: none; } .lst-kix_list_2-5 > li::before { content: "■ "; } ul.lst-kix_list_d-1 { list-style-type: none; } ul.lst-kix_list_d-0 { list-style-type: none; } .lst-kix_list_b-8 > li::before { content: "■ "; } ul.lst-kix_list_d-5 { list-style-type: none; } ul.lst-kix_list_d-4 { list-style-type: none; } ul.lst-kix_list_d-3 { list-style-type: none; } ul.lst-kix_list_d-2 { list-style-type: none; } ul.lst-kix_list_1a-0 { list-style-type: none; } ul.lst-kix_list_1a-1 { list-style-type: none; } .lst-kix_list_b-4 > li::before { content: "■ "; } .lst-kix_list_18-6 > li::before { content: "■ "; } ul.lst-kix_list_3-7 { list-style-type: none; } ul.lst-kix_list_1a-2 { list-style-type: none; } ul.lst-kix_list_3-8 { list-style-type: none; } ul.lst-kix_list_1a-3 { list-style-type: none; } ul.lst-kix_list_1a-4 { list-style-type: none; } .lst-kix_list_10-1 > li::before { content: "○ "; } ul.lst-kix_list_1a-5 { list-style-type: none; } .lst-kix_list_18-4 > li::before { content: "■ "; } .lst-kix_list_18-8 > li::before { content: "■ "; } ul.lst-kix_list_1a-6 { list-style-type: none; } ul.lst-kix_list_1a-7 { list-style-type: none; } ul.lst-kix_list_3-1 { list-style-type: none; } ul.lst-kix_list_3-2 { list-style-type: none; } ul.lst-kix_list_3-0 { list-style-type: none; } ul.lst-kix_list_3-5 { list-style-type: none; } ul.lst-kix_list_3-6 { list-style-type: none; } .lst-kix_list_b-6 > li::before { content: "■ "; } ul.lst-kix_list_3-3 { list-style-type: none; } ul.lst-kix_list_3-4 { list-style-type: none; } .lst-kix_list_10-7 > li::before { content: "■ "; } .lst-kix_list_10-5 > li::before { content: "■ "; } .lst-kix_list_10-3 > li::before { content: "■ "; } ul.lst-kix_list_11-7 { list-style-type: none; } ul.lst-kix_list_11-6 { list-style-type: none; } .lst-kix_list_b-0 > li::before { content: "● "; } ul.lst-kix_list_11-5 { list-style-type: none; } ul.lst-kix_list_11-4 { list-style-type: none; } ul.lst-kix_list_11-3 { list-style-type: none; } ul.lst-kix_list_11-2 { list-style-type: none; } .lst-kix_list_b-2 > li::before { content: "■ "; } ul.lst-kix_list_11-1 { list-style-type: none; } ul.lst-kix_list_11-0 { list-style-type: none; } .lst-kix_list_9-2 > li::before { content: "■ "; } ul.lst-kix_list_11-8 { list-style-type: none; } .lst-kix_list_9-0 > li::before { content: "● "; } ul.lst-kix_list_c-8 { list-style-type: none; } ul.lst-kix_list_c-7 { list-style-type: none; } .lst-kix_list_9-6 > li::before { content: "■ "; } ul.lst-kix_list_c-2 { list-style-type: none; } ul.lst-kix_list_c-1 { list-style-type: none; } ul.lst-kix_list_c-0 { list-style-type: none; } .lst-kix_list_9-4 > li::before { content: "■ "; } ul.lst-kix_list_c-6 { list-style-type: none; } .lst-kix_list_a-0 > li::before { content: "● "; } ul.lst-kix_list_c-5 { list-style-type: none; } .lst-kix_list_11-3 > li::before { content: "■ "; } ul.lst-kix_list_c-4 { list-style-type: none; } ul.lst-kix_list_c-3 { list-style-type: none; } ul.lst-kix_list_2-8 { list-style-type: none; } .lst-kix_list_11-5 > li::before { content: "■ "; } ul.lst-kix_list_2-2 { list-style-type: none; } .lst-kix_list_1a-4 > li::before { content: "■ "; } ul.lst-kix_list_2-3 { list-style-type: none; } ul.lst-kix_list_2-0 { list-style-type: none; } ul.lst-kix_list_2-1 { list-style-type: none; } .lst-kix_list_9-8 > li::before { content: "■ "; } ul.lst-kix_list_2-6 { list-style-type: none; } .lst-kix_list_1a-2 > li::before { content: "■ "; } .lst-kix_list_1-1 > li::before { content: "○ "; } ul.lst-kix_list_2-7 { list-style-type: none; } .lst-kix_list_11-7 > li::before { content: "■ "; } ul.lst-kix_list_2-4 { list-style-type: none; } ul.lst-kix_list_2-5 { list-style-type: none; } ul.lst-kix_list_10-0 { list-style-type: none; } .lst-kix_list_1a-0 > li::before { content: "● "; } .lst-kix_list_1-3 > li::before { content: "■ "; } ul.lst-kix_list_10-8 { list-style-type: none; } ul.lst-kix_list_1a-8 { list-style-type: none; } ul.lst-kix_list_10-7 { list-style-type: none; } .lst-kix_list_1-7 > li::before { content: "■ "; } ul.lst-kix_list_10-6 { list-style-type: none; } ul.lst-kix_list_10-5 { list-style-type: none; } ul.lst-kix_list_10-4 { list-style-type: none; } ul.lst-kix_list_10-3 { list-style-type: none; } .lst-kix_list_1-5 > li::before { content: "■ "; } ul.lst-kix_list_10-2 { list-style-type: none; } ul.lst-kix_list_10-1 { list-style-type: none; } .lst-kix_list_2-1 > li::before { content: "○ "; } .lst-kix_list_2-3 > li::before { content: "■ "; } .lst-kix_list_3-1 > li::before { content: "○ "; } .lst-kix_list_3-2 > li::before { content: "■ "; } .lst-kix_list_8-1 > li::before { content: "○ "; } .lst-kix_list_8-2 > li::before { content: "■ "; } .lst-kix_list_3-5 > li::before { content: "■ "; } .lst-kix_list_f-8 > li::before { content: "■ "; } .lst-kix_list_8-5 > li::before { content: "■ "; } .lst-kix_list_8-6 > li::before { content: "■ "; } .lst-kix_list_3-6 > li::before { content: "■ "; } .lst-kix_list_f-4 > li::before { content: "■ "; } .lst-kix_list_a-8 > li::before { content: "■ "; } .lst-kix_list_f-5 > li::before { content: "■ "; } .lst-kix_list_11-2 > li::before { content: "■ "; } .lst-kix_list_a-1 > li::before { content: "○ "; } .lst-kix_list_f-0 > li::before { content: "● "; } .lst-kix_list_a-5 > li::before { content: "■ "; } .lst-kix_list_a-4 > li::before { content: "■ "; } .lst-kix_list_f-1 > li::before { content: "○ "; } .lst-kix_list_e-5 > li::before { content: "■ "; } .lst-kix_list_16-6 > li::before { content: "■ "; } .lst-kix_list_17-1 > li::before { content: "○ "; } .lst-kix_list_e-4 > li::before { content: "■ "; } .lst-kix_list_16-1 > li::before { content: "○ "; } .lst-kix_list_16-2 > li::before { content: "■ "; } .lst-kix_list_e-1 > li::before { content: "○ "; } .lst-kix_list_16-5 > li::before { content: "■ "; } .lst-kix_list_e-0 > li::before { content: "● "; } .lst-kix_list_17-2 > li::before { content: "■ "; } .lst-kix_list_17-6 > li::before { content: "■ "; } .lst-kix_list_17-5 > li::before { content: "■ "; } .lst-kix_list_2-6 > li::before { content: "■ "; } .lst-kix_list_7-1 > li::before { content: "○ "; } .lst-kix_list_7-5 > li::before { content: "■ "; } .lst-kix_list_b-5 > li::before { content: "■ "; } .lst-kix_list_18-5 > li::before { content: "■ "; } .lst-kix_list_13-6 > li::before { content: "■ "; } .lst-kix_list_15-6 > li::before { content: "■ "; } .lst-kix_list_b-1 > li::before { content: "○ "; } .lst-kix_list_10-2 > li::before { content: "■ "; } .lst-kix_list_4-2 > li::before { content: "■ "; } .lst-kix_list_4-6 > li::before { content: "■ "; } .lst-kix_list_15-2 > li::before { content: "■ "; } .lst-kix_list_10-6 > li::before { content: "■ "; } .lst-kix_list_9-1 > li::before { content: "○ "; } .lst-kix_list_e-8 > li::before { content: "■ "; } .lst-kix_list_9-5 > li::before { content: "■ "; } .lst-kix_list_12-2 > li::before { content: "■ "; } .lst-kix_list_11-6 > li::before { content: "■ "; } .lst-kix_list_1-2 > li::before { content: "■ "; } .lst-kix_list_1a-1 > li::before { content: "○ "; } .lst-kix_list_1-6 > li::before { content: "■ "; } .lst-kix_list_12-6 > li::before { content: "■ "; } .lst-kix_list_2-2 > li::before { content: "■ "; } .lst-kix_list_13-2 > li::before { content: "■ "; } ------MultipartBoundary--zmGvipyjWUpT0gAfLJbw3hmbaeNqVxyLAosKXVU9r0---- Content-Type: image/png Content-Transfer-Encoding: binary Content-Location: https://ssl.gstatic.com/docs/common/mobileweb_sprite1.png PNG  IHDR$ UIDATh[[lWΙٛn 8Ik'm\*VEBj51/T5PZ&чJ *ch ܀B)I+!XNHbr:w*>z˅ۦz,3?0u%K/ݚ=sl, XGfѪڎꂒ"ԷU L*ݟ(9 ?/(ϥdb}۽TAq(&c~@̸ ($ L Dҩ:?slxt4eHY' L]; tzMc;#) >bs{SSL.#T<@Sc$T ǝ)9 0*e,Ok=DDAi?3b'_ OP&^`WX?nf0[ט> 2P_"cTd"$`i6'WjEŒF V*4 +7I ;f,RlxLwMÕ=f13dtb zM}b-`"@2)q.wJQ-ޙX=r1/caOڭxfֆ x ӏUbX'Wo}fPb3\=~*kULi_mpIe=$S5~ zS0McH^Z&:9 ([ k5|ǡ8=ˮI$;=e?:HoFy, FXQcC7 aN#Q3ZGH:9%m@  8U#'ږKN{ūvF±01ߜFˮӳN,PcT^>z_<^KGc5yۉg_I 49f1|Yډ4FF,NGuA)jUXd:8A$lkC50'S[=+ tbbٱѓfcPg%w-\c)m* "<%i1lBDc 1(/™3sbΙ4 C kW!BUde6V$ 9iMX\٩ \AN1Ba >O \';2LV(\v "]Le6 \Ėe|v$``hʂ)gzEN 2W_Vnhhp~ `*,#rDv NjU,bO -a-ST?+%ߘqw2Yȋ<#je\(܃PTbC1BDP1<&xܞeUGcH@cdp c#g93#;^K@Kct$ ߿1i0yOZh@}..M.'|f|FŌs M ̂дfki0[o&0T`l` B' LZfbS~8X'7"l[S7Ļ;3A6 킀xgW5l|k?XFk?Hp^[:n?b, L/c@ұ+&3lޒ<0])ᜂKhd VWmI7+c\,)ݮP*?Z/0pŹ u|ԾUB)]+KƔ8s?Z+r`כּe MԶ2Cy|MfS&9ѽ̄i/%ڝfP' սµ[=ߌX?V/$ 5c,b1HBSȿE+5@{ 4(:]