Pārlūkot izejas kodu

fix: purchase master

Muhammad Iqbal Afandi 4 gadus atpakaļ
vecāks
revīzija
36cc751578

+ 60
- 39
app/Http/Controllers/PurchaseController.php Parādīt failu

@@ -5,7 +5,6 @@ namespace App\Http\Controllers;
5 5
 use App\Http\Requests\Purchase\StorePurchaseRequest;
6 6
 use App\Http\Requests\Purchase\UpdatePurchaseRequest;
7 7
 use App\Models\Ppn;
8
-use App\Models\Price;
9 8
 use App\Models\Product;
10 9
 use App\Models\Purchase;
11 10
 use App\Models\StockProduct;
@@ -44,9 +43,7 @@ class PurchaseController extends Controller
44 43
                         "name" => $purchase->supplier->name,
45 44
                         "phone" => $purchase->supplier->phone,
46 45
                         "price" => HelperService::setRupiahFormat(
47
-                            PurchaseService::totalPrice(
48
-                                $purchase->purchaseDetail
49
-                            )
46
+                            PurchaseService::totalPrice($purchase)
50 47
                         ),
51 48
                         "status" => $purchase->status,
52 49
                     ]
@@ -93,36 +90,20 @@ class PurchaseController extends Controller
93 90
                 ->safe()
94 91
                 ->merge([
95 92
                     "user_id" => auth()->user()->id,
93
+                    "ppn" => $request->ppn ? $ppn : 0,
96 94
                 ])
97 95
                 ->all();
98 96
 
99 97
             $purchase = Purchase::create($validated);
100 98
 
101 99
             foreach ($request->products as $product) {
102
-                $validated = $request
103
-                    ->safe()
104
-                    ->merge([
105
-                        "product_number" => $product["number"],
106
-                        "name" => $product["name"],
107
-                        "price" => $product["price"],
108
-                        "qty" => $product["qty"],
109
-                        "ppn" => $request->ppn ? $ppn : 0,
110
-                    ])
111
-                    ->all();
100
+                $validated = [
101
+                    "product_number" => $product["number"],
102
+                    "price" => $product["price"],
103
+                    "qty" => $product["qty"],
104
+                ];
112 105
 
113 106
                 $purchase->purchaseDetail()->create($validated);
114
-
115
-                $validated = $request
116
-                    ->safe()
117
-                    ->merge([
118
-                        "product_number" => $product["number"],
119
-                        "price" => $request->ppn
120
-                            ? PurchaseService::priceWithPpn($product["price"])
121
-                            : 0,
122
-                    ])
123
-                    ->all();
124
-
125
-                Price::create($validated);
126 107
             }
127 108
 
128 109
             DB::commit();
@@ -157,7 +138,27 @@ class PurchaseController extends Controller
157 138
      */
158 139
     public function edit(Purchase $purchase)
159 140
     {
160
-        return inertia("Purchases/Edit");
141
+        return inertia("Purchases/Edit", [
142
+            "id" => $purchase->id,
143
+            "number" => $purchase->number,
144
+            "ppn" => Ppn::first()->ppn,
145
+            "productNumber" => "PDK" . now()->format("YmdHis"),
146
+            "ppnChecked" => $purchase->ppn ? true : false,
147
+            "supplier" => $purchase->supplier,
148
+            "products" => Inertia::lazy(
149
+                fn() => Product::filter(["search" => request("product")])->get()
150
+            ),
151
+            "purchaseDetail" => $purchase->purchaseDetail->transform(
152
+                fn($purchase) => [
153
+                    "id" => $purchase->id,
154
+                    "number" => $purchase->product_number,
155
+                    "name" => $purchase->product->name,
156
+                    "price" => $purchase->price,
157
+                    "qty" => $purchase->qty,
158
+                    "unit" => $purchase->product->unit,
159
+                ]
160
+            ),
161
+        ]);
161 162
     }
162 163
 
163 164
     /**
@@ -169,24 +170,44 @@ class PurchaseController extends Controller
169 170
      */
170 171
     public function update(UpdatePurchaseRequest $request, Purchase $purchase)
171 172
     {
172
-        dd($request->validated);
173
-
174 173
         DB::beginTransaction();
175 174
 
176 175
         try {
177
-            $purchase->update($request->validated());
176
+            $ppn = Ppn::first()->ppn;
178 177
 
179
-            $purchase
180
-                ->purchaseDetail()
181
-                ->update($request->safe()->except("status"));
178
+            $validated = $request
179
+                ->safe()
180
+                ->merge([
181
+                    "ppn" => $request->ppn ? $ppn : 0,
182
+                ])
183
+                ->all();
184
+
185
+            $purchase->update($validated);
182 186
 
183
-            if ($request->status === "success") {
184
-                StockProduct::create([
187
+            foreach ($request->products as $product) {
188
+                $validated = [
189
+                    "product_number" => $product["number"],
190
+                    "price" => $product["price"],
191
+                    "qty" => $product["qty"],
192
+                ];
193
+
194
+                if (empty($product["id"])) {
195
+                    $purchase->purchaseDetail()->create($validated);
196
+                } else {
197
+                    $purchase->purchaseDetail
198
+                        ->find($product["id"])
199
+                        ->update($validated);
200
+                }
201
+
202
+                $validated = [
185 203
                     "purchase_number" => $purchase->number,
186
-                    "qty" => $request->qty,
187
-                    "product_number" =>
188
-                        $purchase->purchaseDetail->product_number,
189
-                ]);
204
+                    "qty" => $product["qty"],
205
+                    "product_number" => $product["number"],
206
+                ];
207
+
208
+                if ($request->status === "success") {
209
+                    StockProduct::create($validated);
210
+                }
190 211
             }
191 212
 
192 213
             DB::commit();

+ 2
- 2
app/Http/Requests/Purchase/UpdatePurchaseRequest.php Parādīt failu

@@ -25,8 +25,8 @@ class UpdatePurchaseRequest extends FormRequest
25 25
     {
26 26
         return [
27 27
             "status" => "required|string",
28
-            "price" => "required|numeric",
29
-            "qty" => "required|numeric",
28
+            "products" => "required",
29
+            "ppn" => "required|boolean",
30 30
         ];
31 31
     }
32 32
 }

+ 0
- 18
app/Models/Price.php Parādīt failu

@@ -1,18 +0,0 @@
1
-<?php
2
-
3
-namespace App\Models;
4
-
5
-use Illuminate\Database\Eloquent\Factories\HasFactory;
6
-use Illuminate\Database\Eloquent\Model;
7
-
8
-class Price extends Model
9
-{
10
-    use HasFactory;
11
-
12
-    protected $fillable = [
13
-        "price",
14
-        "product_number",
15
-        "customer_id",
16
-        "supplier_id",
17
-    ];
18
-}

+ 1
- 13
app/Models/Purchase.php Parādīt failu

@@ -11,7 +11,7 @@ class Purchase extends Model
11 11
 {
12 12
     use HasFactory;
13 13
 
14
-    protected $fillable = ["number", "status", "supplier_id", "user_id"];
14
+    protected $fillable = ["number", "ppn", "status", "supplier_id", "user_id"];
15 15
 
16 16
     protected function updatedAt(): Attribute
17 17
     {
@@ -31,18 +31,6 @@ class Purchase extends Model
31 31
         );
32 32
     }
33 33
 
34
-    public function product()
35
-    {
36
-        return $this->hasOneThrough(
37
-            Product::class,
38
-            PurchaseDetail::class,
39
-            "purchase_number",
40
-            "number",
41
-            "number",
42
-            "product_number"
43
-        );
44
-    }
45
-
46 34
     public function supplier()
47 35
     {
48 36
         return $this->belongsTo(Supplier::class);

+ 6
- 7
app/Models/PurchaseDetail.php Parādīt failu

@@ -11,11 +11,10 @@ class PurchaseDetail extends Model
11 11
 {
12 12
     use HasFactory;
13 13
 
14
-    protected $fillable = [
15
-        "price",
16
-        "ppn",
17
-        "qty",
18
-        "purchase_number",
19
-        "product_number",
20
-    ];
14
+    protected $fillable = ["price", "qty", "purchase_number", "product_number"];
15
+
16
+    public function product()
17
+    {
18
+        return $this->belongsTo(Product::class, "product_number", "number");
19
+    }
21 20
 }

+ 1
- 1
app/Models/Sale.php Parādīt failu

@@ -11,7 +11,7 @@ class Sale extends Model
11 11
 {
12 12
     use HasFactory;
13 13
 
14
-    protected $fillable = ["number", "status", "customer_id", "user_id"];
14
+    protected $fillable = ["number", "ppn", "status", "customer_id", "user_id"];
15 15
 
16 16
     protected function updatedAt(): Attribute
17 17
     {

+ 1
- 7
app/Models/SaleDetail.php Parādīt failu

@@ -11,11 +11,5 @@ class SaleDetail extends Model
11 11
 {
12 12
     use HasFactory;
13 13
 
14
-    protected $fillable = [
15
-        "price",
16
-        "ppn",
17
-        "qty",
18
-        "sale_number",
19
-        "product_number",
20
-    ];
14
+    protected $fillable = ["price", "qty", "sale_number", "product_number"];
21 15
 }

+ 10
- 11
app/Services/PurchaseService.php Parādīt failu

@@ -2,21 +2,20 @@
2 2
 namespace App\Services;
3 3
 
4 4
 use App\Models\Ppn;
5
-use Illuminate\Database\Eloquent\Collection;
5
+use App\Models\Purchase;
6 6
 
7 7
 class PurchaseService
8 8
 {
9
-    public static function totalPrice(Collection $purchaseDetail)
9
+    public static function totalPrice(Purchase $purchase)
10 10
     {
11
-        return $purchaseDetail->sum(function ($purchase) {
12
-            return self::priceWithPpn($purchase->price);
13
-        });
14
-    }
11
+        return $purchase->purchaseDetail->sum(function ($purchaseDetail) use (
12
+            $purchase
13
+        ) {
14
+            $ppn = Ppn::first()->ppn;
15 15
 
16
-    public static function priceWithPpn(int $price)
17
-    {
18
-        $ppn = Ppn::first()->ppn;
19
-
20
-        return $price + $price * ($ppn / 100);
16
+            return $purchase->ppn
17
+                ? $purchaseDetail->price + $purchaseDetail->price * ($ppn / 100)
18
+                : $purchaseDetail->price;
19
+        });
21 20
     }
22 21
 }

+ 8
- 8
database/migrations/2022_06_16_091424_create_purchases_table.php Parādīt failu

@@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration;
4 4
 use Illuminate\Database\Schema\Blueprint;
5 5
 use Illuminate\Support\Facades\Schema;
6 6
 
7
-return new class extends Migration
8
-{
7
+return new class extends Migration {
9 8
     /**
10 9
      * Run the migrations.
11 10
      *
@@ -13,12 +12,13 @@ return new class extends Migration
13 12
      */
14 13
     public function up()
15 14
     {
16
-        Schema::create('purchases', function (Blueprint $table) {
15
+        Schema::create("purchases", function (Blueprint $table) {
17 16
             $table->id();
18
-            $table->string('number')->unique();
19
-            $table->enum('status', ['pending', 'success']);
20
-            $table->foreignId('supplier_id')->constrained();
21
-            $table->foreignId('user_id')->constrained();
17
+            $table->string("number")->unique();
18
+            $table->unsignedTinyInteger("ppn");
19
+            $table->enum("status", ["pending", "success"]);
20
+            $table->foreignId("supplier_id")->constrained();
21
+            $table->foreignId("user_id")->constrained();
22 22
             $table->timestamps();
23 23
         });
24 24
     }
@@ -30,6 +30,6 @@ return new class extends Migration
30 30
      */
31 31
     public function down()
32 32
     {
33
-        Schema::dropIfExists('purchases');
33
+        Schema::dropIfExists("purchases");
34 34
     }
35 35
 };

+ 8
- 8
database/migrations/2022_06_16_091443_create_sales_table.php Parādīt failu

@@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration;
4 4
 use Illuminate\Database\Schema\Blueprint;
5 5
 use Illuminate\Support\Facades\Schema;
6 6
 
7
-return new class extends Migration
8
-{
7
+return new class extends Migration {
9 8
     /**
10 9
      * Run the migrations.
11 10
      *
@@ -13,12 +12,13 @@ return new class extends Migration
13 12
      */
14 13
     public function up()
15 14
     {
16
-        Schema::create('sales', function (Blueprint $table) {
15
+        Schema::create("sales", function (Blueprint $table) {
17 16
             $table->id();
18
-            $table->string('number')->unique();
19
-            $table->enum('status', ['pending', 'success']);
20
-            $table->foreignId('customer_id')->constrained();
21
-            $table->foreignId('user_id')->constrained();
17
+            $table->string("number")->unique();
18
+            $table->unsignedTinyInteger("ppn");
19
+            $table->enum("status", ["pending", "success"]);
20
+            $table->foreignId("customer_id")->constrained();
21
+            $table->foreignId("user_id")->constrained();
22 22
             $table->timestamps();
23 23
         });
24 24
     }
@@ -30,6 +30,6 @@ return new class extends Migration
30 30
      */
31 31
     public function down()
32 32
     {
33
-        Schema::dropIfExists('sales');
33
+        Schema::dropIfExists("sales");
34 34
     }
35 35
 };

+ 17
- 9
database/migrations/2022_06_16_092657_create_stock_products_table.php Parādīt failu

@@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration;
4 4
 use Illuminate\Database\Schema\Blueprint;
5 5
 use Illuminate\Support\Facades\Schema;
6 6
 
7
-return new class extends Migration
8
-{
7
+return new class extends Migration {
9 8
     /**
10 9
      * Run the migrations.
11 10
      *
@@ -13,13 +12,22 @@ return new class extends Migration
13 12
      */
14 13
     public function up()
15 14
     {
16
-        Schema::create('stock_products', function (Blueprint $table) {
15
+        Schema::create("stock_products", function (Blueprint $table) {
17 16
             $table->id();
18
-            $table->string('purchase_number')->nullable()->default(null);
19
-            $table->string('sale_number')->nullable()->default(null);
20
-            $table->integer('qty');
21
-            $table->string('product_number');
22
-            $table->foreign('product_number')->references('number')->on('products');
17
+            $table
18
+                ->string("purchase_number")
19
+                ->nullable()
20
+                ->default(null);
21
+            $table
22
+                ->string("sale_number")
23
+                ->nullable()
24
+                ->default(null);
25
+            $table->integer("qty");
26
+            $table->string("product_number");
27
+            $table
28
+                ->foreign("product_number")
29
+                ->references("number")
30
+                ->on("products");
23 31
             $table->timestamps();
24 32
         });
25 33
     }
@@ -31,6 +39,6 @@ return new class extends Migration
31 39
      */
32 40
     public function down()
33 41
     {
34
-        Schema::dropIfExists('stock_products');
42
+        Schema::dropIfExists("stock_products");
35 43
     }
36 44
 };

+ 0
- 36
database/migrations/2022_06_17_115146_create_prices_table.php Parādīt failu

@@ -1,36 +0,0 @@
1
-<?php
2
-
3
-use Illuminate\Database\Migrations\Migration;
4
-use Illuminate\Database\Schema\Blueprint;
5
-use Illuminate\Support\Facades\Schema;
6
-
7
-return new class extends Migration
8
-{
9
-    /**
10
-     * Run the migrations.
11
-     *
12
-     * @return void
13
-     */
14
-    public function up()
15
-    {
16
-        Schema::create('prices', function (Blueprint $table) {
17
-            $table->id();
18
-            $table->unsignedBigInteger('price');
19
-            $table->string('product_number');
20
-            $table->foreign('product_number')->references('number')->on('products');
21
-            $table->foreignId('customer_id')->nullable()->constrained();
22
-            $table->foreignId('supplier_id')->nullable()->constrained();
23
-            $table->timestamps();
24
-        });
25
-    }
26
-
27
-    /**
28
-     * Reverse the migrations.
29
-     *
30
-     * @return void
31
-     */
32
-    public function down()
33
-    {
34
-        Schema::dropIfExists('prices');
35
-    }
36
-};

+ 15
- 11
database/migrations/2022_06_17_115154_create_sale_details_table.php Parādīt failu

@@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration;
4 4
 use Illuminate\Database\Schema\Blueprint;
5 5
 use Illuminate\Support\Facades\Schema;
6 6
 
7
-return new class extends Migration
8
-{
7
+return new class extends Migration {
9 8
     /**
10 9
      * Run the migrations.
11 10
      *
@@ -13,15 +12,20 @@ return new class extends Migration
13 12
      */
14 13
     public function up()
15 14
     {
16
-        Schema::create('sale_details', function (Blueprint $table) {
15
+        Schema::create("sale_details", function (Blueprint $table) {
17 16
             $table->id();
18
-            $table->unsignedInteger('price');
19
-            $table->unsignedTinyInteger('ppn');
20
-            $table->unsignedInteger('qty');
21
-            $table->string('product_number');
22
-            $table->string('sale_number');
23
-            $table->foreign('sale_number')->references('number')->on('sales');
24
-            $table->foreign('product_number')->references('number')->on('products');
17
+            $table->unsignedInteger("price");
18
+            $table->unsignedInteger("qty");
19
+            $table->string("product_number");
20
+            $table->string("sale_number");
21
+            $table
22
+                ->foreign("sale_number")
23
+                ->references("number")
24
+                ->on("sales");
25
+            $table
26
+                ->foreign("product_number")
27
+                ->references("number")
28
+                ->on("products");
25 29
             $table->timestamps();
26 30
         });
27 31
     }
@@ -33,6 +37,6 @@ return new class extends Migration
33 37
      */
34 38
     public function down()
35 39
     {
36
-        Schema::dropIfExists('sale_details');
40
+        Schema::dropIfExists("sale_details");
37 41
     }
38 42
 };

+ 15
- 11
database/migrations/2022_06_17_115201_create_purchase_details_table.php Parādīt failu

@@ -4,8 +4,7 @@ use Illuminate\Database\Migrations\Migration;
4 4
 use Illuminate\Database\Schema\Blueprint;
5 5
 use Illuminate\Support\Facades\Schema;
6 6
 
7
-return new class extends Migration
8
-{
7
+return new class extends Migration {
9 8
     /**
10 9
      * Run the migrations.
11 10
      *
@@ -13,15 +12,20 @@ return new class extends Migration
13 12
      */
14 13
     public function up()
15 14
     {
16
-        Schema::create('purchase_details', function (Blueprint $table) {
15
+        Schema::create("purchase_details", function (Blueprint $table) {
17 16
             $table->id();
18
-            $table->unsignedInteger('price');
19
-            $table->unsignedTinyInteger('ppn');
20
-            $table->unsignedInteger('qty');
21
-            $table->string('purchase_number');
22
-            $table->string('product_number');
23
-            $table->foreign('purchase_number')->references('number')->on('purchases');
24
-            $table->foreign('product_number')->references('number')->on('products');
17
+            $table->unsignedInteger("price");
18
+            $table->unsignedInteger("qty");
19
+            $table->string("purchase_number");
20
+            $table->string("product_number");
21
+            $table
22
+                ->foreign("purchase_number")
23
+                ->references("number")
24
+                ->on("purchases");
25
+            $table
26
+                ->foreign("product_number")
27
+                ->references("number")
28
+                ->on("products");
25 29
             $table->timestamps();
26 30
         });
27 31
     }
@@ -33,6 +37,6 @@ return new class extends Migration
33 37
      */
34 38
     public function down()
35 39
     {
36
-        Schema::dropIfExists('purchase_details');
40
+        Schema::dropIfExists("purchase_details");
37 41
     }
38 42
 };

+ 0
- 132
designs/diagrams/database.puml Parādīt failu

@@ -1,132 +0,0 @@
1
-@startuml Database
2
-
3
-entity User {
4
-  * id
5
-  __
6
-  * name
7
-  * username
8
-  * status
9
-  * password
10
-  __
11
-  * role_id
12
-}
13
-
14
-entity Role {
15
-  * id
16
-  __
17
-  * name
18
-}
19
-
20
-entity Customer {
21
-  * id
22
-  __
23
-  * name
24
-  * address
25
-  * phone
26
-  * npwp
27
-}
28
-
29
-entity Product {
30
-  * id
31
-  __
32
-  * number
33
-  * name
34
-  * unit
35
-  * profit
36
-}
37
-
38
-entity Supplier {
39
-  * id
40
-  __
41
-  * name
42
-  * address
43
-  * phone
44
-  * email
45
-  * npwp
46
-}
47
-
48
-entity Purchase {
49
-  * id
50
-  __
51
-  * number
52
-  * status
53
-  __
54
-  * supplier_id
55
-  * user_id
56
-}
57
-
58
-entity Sale {
59
-  * id
60
-  __
61
-  * number
62
-  * status
63
-  __
64
-  * customer_id
65
-  * user_id
66
-}
67
-
68
-entity StockProduct {
69
-  * id
70
-  __
71
-  * purchase_number
72
-  * sale_number
73
-  * qty
74
-  __
75
-  * product_number
76
-}
77
-
78
-entity Price {
79
-  * id
80
-  __
81
-  * price
82
-  __
83
-  * product_number
84
-  * customer_id
85
-  * supplier_id
86
-}
87
-
88
-entity SaleDetail {
89
-  * id
90
-  __
91
-  * price
92
-  * ppn
93
-  * qty
94
-  __
95
-  * sale_number
96
-  * product_number
97
-}
98
-
99
-entity PurchaseDetail {
100
-  * id
101
-  __
102
-  * price
103
-  * ppn
104
-  * qty
105
-  __
106
-  * purchase_number
107
-  * product_number
108
-}
109
-
110
-entity Ppn {
111
-  * id
112
-  __
113
-  * ppn
114
-}
115
-
116
-User ||--|{ Role
117
-User }|--|| Purchase
118
-User }|--|| Sale
119
-Supplier }|--|| Purchase
120
-Supplier ||--|| Price
121
-Customer ||--|{ Sale
122
-Customer ||--|| Price
123
-Sale ||--|| SaleDetail
124
-Sale ||--|| Price
125
-Purchase }|--|| PurchaseDetail
126
-Purchase ||--|| Price
127
-Purchase ||--|{ StockProduct
128
-SaleDetail ||--|{ Product
129
-Sale ||--|{ StockProduct
130
-PurchaseDetail ||--|{ Product
131
-StockProduct ||--|{ Product
132
-Product ||--|| Price

Binārs
designs/diagrams/database/Database.png Parādīt failu


+ 0
- 172
designs/diagrams/database/Database.svg Parādīt failu

@@ -1,172 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="960px" preserveAspectRatio="none" style="width:789px;height:960px;background:#FFFFFF;" version="1.1" viewBox="0 0 789 960" width="789px" zoomAndPan="magnify"><defs/><g><!--MD5=[3fd616f346a44cd59a91eb10b19e157c]
2
-class User--><g id="elem_User"><rect codeLine="2" fill="#F1F1F1" height="152.5918" id="User" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="89" x="325.18" y="7"/><ellipse cx="352.78" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M348.9206,28.5 L348.9206,17.2969 L356.9519,17.2969 L356.9519,19.1875 L351.3738,19.1875 L351.3738,21.8906 L356.4519,21.8906 L356.4519,23.7813 L351.3738,23.7813 L351.3738,26.6094 L357.2956,26.6094 L357.2956,28.5 L348.9206,28.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="29" x="369.58" y="28.0825">User</text><line style="stroke:#181818;stroke-width:0.5;" x1="326.18" x2="413.18" y1="39" y2="39"/><ellipse cx="336.18" cy="50" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="345.18" y="56.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="326.18" x2="413.18" y1="63.0986" y2="63.0986"/><ellipse cx="336.18" cy="74.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="35" x="345.18" y="80.2305">name</text><ellipse cx="336.18" cy="90.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="63" x="345.18" y="96.3291">username</text><ellipse cx="336.18" cy="106.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38" x="345.18" y="112.4277">status</text><ellipse cx="336.18" cy="122.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="60" x="345.18" y="128.5264">password</text><line style="stroke:#181818;stroke-width:0.5;" x1="326.18" x2="413.18" y1="135.4932" y2="135.4932"/><ellipse cx="336.18" cy="146.4932" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="43" x="345.18" y="152.625">role_id</text></g><!--MD5=[a3638c1e5b65d287ecad7f06f5c0f212]
3
-class Role--><g id="elem_Role"><rect codeLine="13" fill="#F1F1F1" height="80.1973" id="Role" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="61" x="339.18" y="248"/><ellipse cx="354.18" cy="264" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M350.3206,269.5 L350.3206,258.2969 L358.3519,258.2969 L358.3519,260.1875 L352.7738,260.1875 L352.7738,262.8906 L357.8519,262.8906 L357.8519,264.7813 L352.7738,264.7813 L352.7738,267.6094 L358.6956,267.6094 L358.6956,269.5 L350.3206,269.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="29" x="368.18" y="269.0825">Role</text><line style="stroke:#181818;stroke-width:0.5;" x1="340.18" x2="399.18" y1="280" y2="280"/><ellipse cx="350.18" cy="291" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="359.18" y="297.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="340.18" x2="399.18" y1="304.0986" y2="304.0986"/><ellipse cx="350.18" cy="315.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="35" x="359.18" y="321.2305">name</text></g><!--MD5=[2ce0c9fb7f55b1e256ab28a8ea6b25ec]
4
-class Customer--><g id="elem_Customer"><rect codeLine="19" fill="#F1F1F1" height="128.4932" id="Customer" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="93" x="107.18" y="19.5"/><ellipse cx="122.18" cy="35.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M118.3206,41 L118.3206,29.7969 L126.3519,29.7969 L126.3519,31.6875 L120.7738,31.6875 L120.7738,34.3906 L125.8519,34.3906 L125.8519,36.2813 L120.7738,36.2813 L120.7738,39.1094 L126.6956,39.1094 L126.6956,41 L118.3206,41 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="61" x="136.18" y="40.5825">Customer</text><line style="stroke:#181818;stroke-width:0.5;" x1="108.18" x2="199.18" y1="51.5" y2="51.5"/><ellipse cx="118.18" cy="62.5" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="127.18" y="68.6318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="108.18" x2="199.18" y1="75.5986" y2="75.5986"/><ellipse cx="118.18" cy="86.5986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="35" x="127.18" y="92.7305">name</text><ellipse cx="118.18" cy="102.6973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="51" x="127.18" y="108.8291">address</text><ellipse cx="118.18" cy="118.7959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="40" x="127.18" y="124.9277">phone</text><ellipse cx="118.18" cy="134.8945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="33" x="127.18" y="141.0264">npwp</text></g><!--MD5=[72136138052d025cffdce3c22fbd185f]
5
-class Product--><g id="elem_Product"><rect codeLine="28" fill="#F1F1F1" height="128.4932" id="Product" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="81" x="334.18" y="629"/><ellipse cx="349.18" cy="645" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M345.3206,650.5 L345.3206,639.2969 L353.3519,639.2969 L353.3519,641.1875 L347.7738,641.1875 L347.7738,643.8906 L352.8519,643.8906 L352.8519,645.7813 L347.7738,645.7813 L347.7738,648.6094 L353.6956,648.6094 L353.6956,650.5 L345.3206,650.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="363.18" y="650.0825">Product</text><line style="stroke:#181818;stroke-width:0.5;" x1="335.18" x2="414.18" y1="661" y2="661"/><ellipse cx="345.18" cy="672" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="354.18" y="678.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="335.18" x2="414.18" y1="685.0986" y2="685.0986"/><ellipse cx="345.18" cy="696.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="48" x="354.18" y="702.2305">number</text><ellipse cx="345.18" cy="712.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="35" x="354.18" y="718.3291">name</text><ellipse cx="345.18" cy="728.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="23" x="354.18" y="734.4277">unit</text><ellipse cx="345.18" cy="744.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="32" x="354.18" y="750.5264">profit</text></g><!--MD5=[6f6af049516bc56aac6e320b3234ce97]
6
-class Supplier--><g id="elem_Supplier"><rect codeLine="37" fill="#F1F1F1" height="144.5918" id="Supplier" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="84" x="605.68" y="11"/><ellipse cx="620.68" cy="27" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M616.8206,32.5 L616.8206,21.2969 L624.8519,21.2969 L624.8519,23.1875 L619.2738,23.1875 L619.2738,25.8906 L624.3519,25.8906 L624.3519,27.7813 L619.2738,27.7813 L619.2738,30.6094 L625.1956,30.6094 L625.1956,32.5 L616.8206,32.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="52" x="634.68" y="32.0825">Supplier</text><line style="stroke:#181818;stroke-width:0.5;" x1="606.68" x2="688.68" y1="43" y2="43"/><ellipse cx="616.68" cy="54" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="625.68" y="60.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="606.68" x2="688.68" y1="67.0986" y2="67.0986"/><ellipse cx="616.68" cy="78.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="35" x="625.68" y="84.2305">name</text><ellipse cx="616.68" cy="94.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="51" x="625.68" y="100.3291">address</text><ellipse cx="616.68" cy="110.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="40" x="625.68" y="116.4277">phone</text><ellipse cx="616.68" cy="126.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="33" x="625.68" y="132.5264">email</text><ellipse cx="616.68" cy="142.4932" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="33" x="625.68" y="148.625">npwp</text></g><!--MD5=[ca228764f84c38a6bbd29bae3074bbc7]
7
-class Purchase--><g id="elem_Purchase"><rect codeLine="47" fill="#F1F1F1" height="136.4932" id="Purchase" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="95" x="503.18" y="220"/><ellipse cx="519.53" cy="236" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M515.6706,241.5 L515.6706,230.2969 L523.7019,230.2969 L523.7019,232.1875 L518.1238,232.1875 L518.1238,234.8906 L523.2019,234.8906 L523.2019,236.7813 L518.1238,236.7813 L518.1238,239.6094 L524.0456,239.6094 L524.0456,241.5 L515.6706,241.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="60" x="533.83" y="241.0825">Purchase</text><line style="stroke:#181818;stroke-width:0.5;" x1="504.18" x2="597.18" y1="252" y2="252"/><ellipse cx="514.18" cy="263" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="523.18" y="269.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="504.18" x2="597.18" y1="276.0986" y2="276.0986"/><ellipse cx="514.18" cy="287.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="48" x="523.18" y="293.2305">number</text><ellipse cx="514.18" cy="303.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38" x="523.18" y="309.3291">status</text><line style="stroke:#181818;stroke-width:0.5;" x1="504.18" x2="597.18" y1="316.2959" y2="316.2959"/><ellipse cx="514.18" cy="327.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="69" x="523.18" y="333.4277">supplier_id</text><ellipse cx="514.18" cy="343.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="47" x="523.18" y="349.5264">user_id</text></g><!--MD5=[e0bd77868626c22cfc0c5aeed1b8d67f]
8
-class Sale--><g id="elem_Sale"><rect codeLine="57" fill="#F1F1F1" height="136.4932" id="Sale" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="103" x="152.18" y="220"/><ellipse cx="186.53" cy="236" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M182.6706,241.5 L182.6706,230.2969 L190.7019,230.2969 L190.7019,232.1875 L185.1238,232.1875 L185.1238,234.8906 L190.2019,234.8906 L190.2019,236.7813 L185.1238,236.7813 L185.1238,239.6094 L191.0456,239.6094 L191.0456,241.5 L182.6706,241.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="28" x="204.83" y="241.0825">Sale</text><line style="stroke:#181818;stroke-width:0.5;" x1="153.18" x2="254.18" y1="252" y2="252"/><ellipse cx="163.18" cy="263" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="172.18" y="269.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="153.18" x2="254.18" y1="276.0986" y2="276.0986"/><ellipse cx="163.18" cy="287.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="48" x="172.18" y="293.2305">number</text><ellipse cx="163.18" cy="303.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38" x="172.18" y="309.3291">status</text><line style="stroke:#181818;stroke-width:0.5;" x1="153.18" x2="254.18" y1="316.2959" y2="316.2959"/><ellipse cx="163.18" cy="327.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="172.18" y="333.4277">customer_id</text><ellipse cx="163.18" cy="343.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="47" x="172.18" y="349.5264">user_id</text></g><!--MD5=[0cfc926ac851c171b4800cdea9975fdf]
9
-class StockProduct--><g id="elem_StockProduct"><rect codeLine="67" fill="#F1F1F1" height="136.4932" id="StockProduct" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="141" x="304.18" y="424.5"/><ellipse cx="330.43" cy="440.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M326.5706,446 L326.5706,434.7969 L334.6019,434.7969 L334.6019,436.6875 L329.0238,436.6875 L329.0238,439.3906 L334.1019,439.3906 L334.1019,441.2813 L329.0238,441.2813 L329.0238,444.1094 L334.9456,444.1094 L334.9456,446 L326.5706,446 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="346.93" y="445.5825">StockProduct</text><line style="stroke:#181818;stroke-width:0.5;" x1="305.18" x2="444.18" y1="456.5" y2="456.5"/><ellipse cx="315.18" cy="467.5" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="324.18" y="473.6318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="305.18" x2="444.18" y1="480.5986" y2="480.5986"/><ellipse cx="315.18" cy="491.5986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="324.18" y="497.7305">purchase_number</text><ellipse cx="315.18" cy="507.6973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="82" x="324.18" y="513.8291">sale_number</text><ellipse cx="315.18" cy="523.7959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="19" x="324.18" y="529.9277">qty</text><line style="stroke:#181818;stroke-width:0.5;" x1="305.18" x2="444.18" y1="536.8945" y2="536.8945"/><ellipse cx="315.18" cy="547.8945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="104" x="324.18" y="554.0264">product_number</text></g><!--MD5=[a40a7ac4b423335b0d34bf16cf36e547]
10
-class Price--><g id="elem_Price"><rect codeLine="77" fill="#F1F1F1" height="136.4932" id="Price" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="130" x="309.68" y="817"/><ellipse cx="354.43" cy="833" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M350.5706,838.5 L350.5706,827.2969 L358.6019,827.2969 L358.6019,829.1875 L353.0238,829.1875 L353.0238,831.8906 L358.1019,831.8906 L358.1019,833.7813 L353.0238,833.7813 L353.0238,836.6094 L358.9456,836.6094 L358.9456,838.5 L350.5706,838.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="32" x="374.93" y="838.0825">Price</text><line style="stroke:#181818;stroke-width:0.5;" x1="310.68" x2="438.68" y1="849" y2="849"/><ellipse cx="320.68" cy="860" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="329.68" y="866.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="310.68" x2="438.68" y1="873.0986" y2="873.0986"/><ellipse cx="320.68" cy="884.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="31" x="329.68" y="890.2305">price</text><line style="stroke:#181818;stroke-width:0.5;" x1="310.68" x2="438.68" y1="897.1973" y2="897.1973"/><ellipse cx="320.68" cy="908.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="104" x="329.68" y="914.3291">product_number</text><ellipse cx="320.68" cy="924.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="329.68" y="930.4277">customer_id</text><ellipse cx="320.68" cy="940.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="69" x="329.68" y="946.5264">supplier_id</text></g><!--MD5=[680168ab3c03721c8f7b2302070ae319]
11
-class SaleDetail--><g id="elem_SaleDetail"><rect codeLine="87" fill="#F1F1F1" height="152.5918" id="SaleDetail" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="130" x="138.68" y="416"/><ellipse cx="168.98" cy="432" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M165.1206,437.5 L165.1206,426.2969 L173.1519,426.2969 L173.1519,428.1875 L167.5738,428.1875 L167.5738,430.8906 L172.6519,430.8906 L172.6519,432.7813 L167.5738,432.7813 L167.5738,435.6094 L173.4956,435.6094 L173.4956,437.5 L165.1206,437.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="64" x="186.38" y="437.0825">SaleDetail</text><line style="stroke:#181818;stroke-width:0.5;" x1="139.68" x2="267.68" y1="448" y2="448"/><ellipse cx="149.68" cy="459" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="158.68" y="465.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="139.68" x2="267.68" y1="472.0986" y2="472.0986"/><ellipse cx="149.68" cy="483.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="31" x="158.68" y="489.2305">price</text><ellipse cx="149.68" cy="499.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="24" x="158.68" y="505.3291">ppn</text><ellipse cx="149.68" cy="515.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="19" x="158.68" y="521.4277">qty</text><line style="stroke:#181818;stroke-width:0.5;" x1="139.68" x2="267.68" y1="528.3945" y2="528.3945"/><ellipse cx="149.68" cy="539.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="82" x="158.68" y="545.5264">sale_number</text><ellipse cx="149.68" cy="555.4932" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="104" x="158.68" y="561.625">product_number</text></g><!--MD5=[3d9bec551640ffb4a026cc7c78c25b79]
12
-class PurchaseDetail--><g id="elem_PurchaseDetail"><rect codeLine="98" fill="#F1F1F1" height="152.5918" id="PurchaseDetail" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="141" x="480.18" y="416"/><ellipse cx="501.03" cy="432" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M497.1706,437.5 L497.1706,426.2969 L505.2019,426.2969 L505.2019,428.1875 L499.6238,428.1875 L499.6238,430.8906 L504.7019,430.8906 L504.7019,432.7813 L499.6238,432.7813 L499.6238,435.6094 L505.5456,435.6094 L505.5456,437.5 L497.1706,437.5 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="96" x="516.33" y="437.0825">PurchaseDetail</text><line style="stroke:#181818;stroke-width:0.5;" x1="481.18" x2="620.18" y1="448" y2="448"/><ellipse cx="491.18" cy="459" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="500.18" y="465.1318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="481.18" x2="620.18" y1="472.0986" y2="472.0986"/><ellipse cx="491.18" cy="483.0986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="31" x="500.18" y="489.2305">price</text><ellipse cx="491.18" cy="499.1973" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="24" x="500.18" y="505.3291">ppn</text><ellipse cx="491.18" cy="515.2959" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="19" x="500.18" y="521.4277">qty</text><line style="stroke:#181818;stroke-width:0.5;" x1="481.18" x2="620.18" y1="528.3945" y2="528.3945"/><ellipse cx="491.18" cy="539.3945" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="500.18" y="545.5264">purchase_number</text><ellipse cx="491.18" cy="555.4932" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="104" x="500.18" y="561.625">product_number</text></g><!--MD5=[c26ae6d58060a6dc125b0061a9f99778]
13
-class Ppn--><g id="elem_Ppn"><rect codeLine="109" fill="#F1F1F1" height="80.1973" id="Ppn" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="57" x="725.18" y="43.5"/><ellipse cx="740.18" cy="59.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M736.3206,65 L736.3206,53.7969 L744.3519,53.7969 L744.3519,55.6875 L738.7738,55.6875 L738.7738,58.3906 L743.8519,58.3906 L743.8519,60.2813 L738.7738,60.2813 L738.7738,63.1094 L744.6956,63.1094 L744.6956,65 L736.3206,65 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="25" x="754.18" y="64.5825">Ppn</text><line style="stroke:#181818;stroke-width:0.5;" x1="726.18" x2="781.18" y1="75.5" y2="75.5"/><ellipse cx="736.18" cy="86.5" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="11" x="745.18" y="92.6318">id</text><line style="stroke:#181818;stroke-width:0.5;" x1="726.18" x2="781.18" y1="99.5986" y2="99.5986"/><ellipse cx="736.18" cy="110.5986" fill="#000000" rx="3" ry="3" style="stroke:#000000;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="24" x="745.18" y="116.7305">ppn</text></g><!--MD5=[70c37dc9bfbc8656942103c36f1181e4]
14
-link User to Role--><g id="link_User_Role"><path codeLine="115" d="M369.68,168.28 C369.68,192.59 369.68,218.27 369.68,239.51 " fill="none" id="User-Role" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="369.68" x2="375.68" y1="239.72" y2="247.72"/><line style="stroke:#181818;stroke-width:1.0;" x1="369.68" x2="363.68" y1="239.72" y2="247.72"/><line style="stroke:#181818;stroke-width:1.0;" x1="369.68" x2="369.68" y1="239.72" y2="247.72"/><line style="stroke:#181818;stroke-width:1.0;" x1="373.68" x2="365.68" y1="237.72" y2="237.72"/><line style="stroke:#181818;stroke-width:1.0;" x1="365.68" x2="373.68" y1="164.19" y2="164.19"/><line style="stroke:#181818;stroke-width:1.0;" x1="365.68" x2="373.68" y1="167.19" y2="167.19"/><line style="stroke:#181818;stroke-width:1.0;" x1="369.68" x2="369.68" y1="168.19" y2="160.19"/></g><!--MD5=[474f0e405c986647f348979b3d9bac30]
15
-link User to Purchase--><g id="link_User_Purchase"><path codeLine="116" d="M419.67,140.42 C443.91,167.54 473.04,200.13 497.67,227.69 " fill="none" id="User-Purchase" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="503.4946" x2="497.5319" y1="228.2019" y2="233.5354"/><line style="stroke:#181818;stroke-width:1.0;" x1="501.4945" x2="495.5318" y1="225.9659" y2="231.2994"/><line style="stroke:#181818;stroke-width:1.0;" x1="497.8465" x2="503.18" y1="227.8873" y2="233.85"/><line style="stroke:#181818;stroke-width:1.0;" x1="419.5235" x2="409.718" y1="140.2627" y2="138.3001"/><line style="stroke:#181818;stroke-width:1.0;" x1="419.5235" x2="418.662" y1="140.2627" y2="130.2999"/><line style="stroke:#181818;stroke-width:1.0;" x1="419.5235" x2="414.19" y1="140.2627" y2="134.3"/><line style="stroke:#181818;stroke-width:1.0;" x1="417.8756" x2="423.8382" y1="144.4201" y2="139.0866"/></g><!--MD5=[fa16bf6141e1c24f8824fff3082d1ce7]
16
-link User to Sale--><g id="link_User_Sale"><path codeLine="117" d="M319.86,145.28 C301.12,168.14 279.67,194.3 260.35,217.87 " fill="none" id="User-Sale" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="260.8593" x2="254.6728" y1="223.5628" y2="218.4907"/><line style="stroke:#181818;stroke-width:1.0;" x1="262.7614" x2="256.5748" y1="221.2428" y2="216.1707"/><line style="stroke:#181818;stroke-width:1.0;" x1="260.3021" x2="255.23" y1="217.9334" y2="224.12"/><line style="stroke:#181818;stroke-width:1.0;" x1="319.9079" x2="320.3401" y1="145.2166" y2="135.2259"/><line style="stroke:#181818;stroke-width:1.0;" x1="319.9079" x2="329.6199" y1="145.2166" y2="142.8341"/><line style="stroke:#181818;stroke-width:1.0;" x1="319.9079" x2="324.98" y1="145.2166" y2="139.03"/><line style="stroke:#181818;stroke-width:1.0;" x1="315.5466" x2="321.7331" y1="144.2271" y2="149.2993"/></g><!--MD5=[4e61cc6c8c4df3951b5a0cc721e44351]
17
-link Supplier to Purchase--><g id="link_Supplier_Purchase"><path codeLine="118" d="M609.83,163.53 C602.1,179.66 593.99,196.59 586.34,212.56 " fill="none" id="Supplier-Purchase" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="588.1958" x2="580.9814" y1="217.9414" y2="214.4842"/><line style="stroke:#181818;stroke-width:1.0;" x1="589.4923" x2="582.2778" y1="215.236" y2="211.7788"/><line style="stroke:#181818;stroke-width:1.0;" x1="586.3172" x2="582.86" y1="212.6056" y2="219.82"/><line style="stroke:#181818;stroke-width:1.0;" x1="609.8928" x2="607.9392" y1="163.3944" y2="153.5871"/><line style="stroke:#181818;stroke-width:1.0;" x1="609.8928" x2="618.7608" y1="163.3944" y2="158.7729"/><line style="stroke:#181818;stroke-width:1.0;" x1="609.8928" x2="613.35" y1="163.3944" y2="156.18"/><line style="stroke:#181818;stroke-width:1.0;" x1="605.4213" x2="612.6357" y1="163.4694" y2="166.9266"/></g><!--MD5=[8dbb028c2b05e4025f5d42a599ab93b5]
18
-link Supplier to Price--><g id="link_Supplier_Price"><path codeLine="119" d="M664.14,163.15 C681.54,259.82 702.67,428.36 672.68,569 C653.6,658.5 649.56,688.66 588.68,757 C549.71,800.75 491.97,833.79 446.29,855.19 " fill="none" id="Supplier-Price" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="445.232" x2="441.865" y1="860.075" y2="852.818"/><line style="stroke:#181818;stroke-width:1.0;" x1="447.9533" x2="444.5864" y1="858.8124" y2="851.5554"/><line style="stroke:#181818;stroke-width:1.0;" x1="447.177" x2="439.92" y1="854.763" y2="858.13"/><line style="stroke:#181818;stroke-width:1.0;" x1="659.6235" x2="667.4934" y1="160.6734" y2="159.2365"/><line style="stroke:#181818;stroke-width:1.0;" x1="660.1623" x2="668.0322" y1="163.6246" y2="162.1878"/><line style="stroke:#181818;stroke-width:1.0;" x1="664.2768" x2="662.84" y1="163.8899" y2="156.02"/></g><!--MD5=[d458a1e609d20b4df6a1b1701aeabf58]
19
-link Customer to Sale--><g id="link_Customer_Sale"><path codeLine="120" d="M171.24,155.62 C175.74,173.83 180.59,193.47 185.14,211.88 " fill="none" id="Customer-Sale" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="185.1433" x2="192.8852" y1="211.913" y2="218.2425"/><line style="stroke:#181818;stroke-width:1.0;" x1="185.1433" x2="181.2348" y1="211.913" y2="221.1175"/><line style="stroke:#181818;stroke-width:1.0;" x1="185.1433" x2="187.06" y1="211.913" y2="219.68"/><line style="stroke:#181818;stroke-width:1.0;" x1="188.5476" x2="180.7806" y1="209.0129" y2="210.9296"/><line style="stroke:#181818;stroke-width:1.0;" x1="166.3812" x2="174.1457" y1="152.5857" y2="150.6588"/><line style="stroke:#181818;stroke-width:1.0;" x1="167.1037" x2="174.8682" y1="155.4974" y2="153.5705"/><line style="stroke:#181818;stroke-width:1.0;" x1="171.2268" x2="169.3" y1="155.5045" y2="147.74"/></g><!--MD5=[ae2c05453d21049e7a5e02ab04069fb0]
20
-link Customer to Price--><g id="link_Customer_Price"><path codeLine="121" d="M127.01,154.51 C81.44,287.23 6,578.11 142.68,757 C182.72,809.4 250.84,842.97 302.95,862.36 " fill="none" id="Customer-Price" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="307.1648" x2="304.406" y1="859.626" y2="867.1352"/><line style="stroke:#181818;stroke-width:1.0;" x1="304.3488" x2="301.59" y1="858.5914" y2="866.1006"/><line style="stroke:#181818;stroke-width:1.0;" x1="302.0307" x2="309.54" y1="862.0012" y2="864.76"/><line style="stroke:#181818;stroke-width:1.0;" x1="124.3429" x2="131.9041" y1="150.0141" y2="152.6271"/><line style="stroke:#181818;stroke-width:1.0;" x1="123.363" x2="130.9243" y1="152.8496" y2="155.4626"/><line style="stroke:#181818;stroke-width:1.0;" x1="126.817" x2="129.43" y1="155.1012" y2="147.54"/></g><!--MD5=[1b8181cc673ea47d6cea814c6d86a94d]
21
-link Sale to SaleDetail--><g id="link_Sale_SaleDetail"><path codeLine="122" d="M203.68,363.39 C203.68,378.07 203.68,393.56 203.68,408.5 " fill="none" id="Sale-SaleDetail" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="207.68" x2="199.68" y1="411.79" y2="411.79"/><line style="stroke:#181818;stroke-width:1.0;" x1="207.68" x2="199.68" y1="408.79" y2="408.79"/><line style="stroke:#181818;stroke-width:1.0;" x1="203.68" x2="203.68" y1="407.79" y2="415.79"/><line style="stroke:#181818;stroke-width:1.0;" x1="199.68" x2="207.68" y1="360.15" y2="360.15"/><line style="stroke:#181818;stroke-width:1.0;" x1="199.68" x2="207.68" y1="363.15" y2="363.15"/><line style="stroke:#181818;stroke-width:1.0;" x1="203.68" x2="203.68" y1="364.15" y2="356.15"/></g><!--MD5=[fd58fb4015992d940e1d5ff8549f8c35]
22
-link Sale to Price--><g id="link_Sale_Price"><path codeLine="123" d="M148.25,358.24 C136.93,376.07 126.66,395.93 120.68,416 C101.28,481.17 98.05,504.88 120.68,569 C156.96,671.77 242.55,765.67 304.36,823.7 " fill="none" id="Sale-Price" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="309.3239" x2="303.8665" y1="822.8565" y2="828.7061"/><line style="stroke:#181818;stroke-width:1.0;" x1="307.1304" x2="301.673" y1="820.81" y2="826.6596"/><line style="stroke:#181818;stroke-width:1.0;" x1="303.6705" x2="309.52" y1="823.0526" y2="828.51"/><line style="stroke:#181818;stroke-width:1.0;" x1="146.5966" x2="153.3052" y1="353.4452" y2="357.8034"/><line style="stroke:#181818;stroke-width:1.0;" x1="144.9623" x2="151.6709" y1="355.961" y2="360.3192"/><line style="stroke:#181818;stroke-width:1.0;" x1="147.7718" x2="152.13" y1="358.9787" y2="352.27"/></g><!--MD5=[c0e5a52b16fbcef22495159b374d909e]
23
-link Purchase to PurchaseDetail--><g id="link_Purchase_PurchaseDetail"><path codeLine="124" d="M550.68,364.31 C550.68,378.37 550.68,393.14 550.68,407.43 " fill="none" id="Purchase-PurchaseDetail" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="554.68" x2="546.68" y1="411.79" y2="411.79"/><line style="stroke:#181818;stroke-width:1.0;" x1="554.68" x2="546.68" y1="408.79" y2="408.79"/><line style="stroke:#181818;stroke-width:1.0;" x1="550.68" x2="550.68" y1="407.79" y2="415.79"/><line style="stroke:#181818;stroke-width:1.0;" x1="550.68" x2="544.68" y1="364.15" y2="356.15"/><line style="stroke:#181818;stroke-width:1.0;" x1="550.68" x2="556.68" y1="364.15" y2="356.15"/><line style="stroke:#181818;stroke-width:1.0;" x1="550.68" x2="550.68" y1="364.15" y2="356.15"/><line style="stroke:#181818;stroke-width:1.0;" x1="546.68" x2="554.68" y1="366.15" y2="366.15"/></g><!--MD5=[9aab0b89b89995cf669aab5ed34799da]
24
-link Purchase to Price--><g id="link_Purchase_Price"><path codeLine="125" d="M602.67,348.16 C617.24,368.32 631.15,391.88 638.68,416 C658.97,480.9 661.92,505.09 638.68,569 C600.38,674.34 509.68,769.01 445.31,826.44 " fill="none" id="Purchase-Price" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="445.5965" x2="440.2927" y1="831.5327" y2="825.5435"/><line style="stroke:#181818;stroke-width:1.0;" x1="447.8424" x2="442.5386" y1="829.5438" y2="823.5546"/><line style="stroke:#181818;stroke-width:1.0;" x1="445.9392" x2="439.95" y1="825.8862" y2="831.19"/><line style="stroke:#181818;stroke-width:1.0;" x1="597.4989" x2="603.934" y1="347.894" y2="343.1411"/><line style="stroke:#181818;stroke-width:1.0;" x1="599.2812" x2="605.7163" y1="350.3071" y2="345.5543"/><line style="stroke:#181818;stroke-width:1.0;" x1="603.0928" x2="598.34" y1="348.7351" y2="342.3"/></g><!--MD5=[d9346253e56b18202ac3beab23dddd24]
25
-link Purchase to StockProduct--><g id="link_Purchase_StockProduct"><path codeLine="126" d="M497.67,350 C479.03,371.45 457.89,395.77 438.46,418.12 " fill="none" id="Purchase-StockProduct" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="438.2727" x2="437.562" y1="418.3273" y2="428.302"/><line style="stroke:#181818;stroke-width:1.0;" x1="438.2727" x2="428.498" y1="418.3273" y2="420.438"/><line style="stroke:#181818;stroke-width:1.0;" x1="438.2727" x2="433.03" y1="418.3273" y2="424.37"/><line style="stroke:#181818;stroke-width:1.0;" x1="442.6047" x2="436.562" y1="419.438" y2="414.1953"/><line style="stroke:#181818;stroke-width:1.0;" x1="497.4168" x2="503.4534" y1="344.1934" y2="349.4432"/><line style="stroke:#181818;stroke-width:1.0;" x1="495.4482" x2="501.4847" y1="346.4571" y2="351.7069"/><line style="stroke:#181818;stroke-width:1.0;" x1="497.8102" x2="503.06" y1="349.8365" y2="343.8"/></g><!--MD5=[cc8c2cf61c441007fd82fc98c1838a15]
26
-link SaleDetail to Product--><g id="link_SaleDetail_Product"><path codeLine="127" d="M274.24,575.41 C292.6,596.72 311.91,619.13 328.64,638.55 " fill="none" id="SaleDetail-Product" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="328.7678" x2="338.5318" y1="638.681" y2="640.8408"/><line style="stroke:#181818;stroke-width:1.0;" x1="328.7678" x2="329.4282" y1="638.681" y2="648.6592"/><line style="stroke:#181818;stroke-width:1.0;" x1="328.7678" x2="333.98" y1="638.681" y2="644.75"/><line style="stroke:#181818;stroke-width:1.0;" x1="330.4992" x2="324.4302" y1="634.5576" y2="639.7698"/><line style="stroke:#181818;stroke-width:1.0;" x1="268.4058" x2="274.4617" y1="574.7517" y2="569.5242"/><line style="stroke:#181818;stroke-width:1.0;" x1="270.3661" x2="276.422" y1="577.0226" y2="571.7951"/><line style="stroke:#181818;stroke-width:1.0;" x1="274.0475" x2="268.82" y1="575.1659" y2="569.11"/></g><!--MD5=[5a75ef0720b826a25eafd7a682d30a1b]
27
-link Sale to StockProduct--><g id="link_Sale_StockProduct"><path codeLine="128" d="M260.62,356.42 C277.31,376.19 295.65,397.91 312.65,418.04 " fill="none" id="Sale-StockProduct" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="312.7221" x2="322.4664" y1="418.1148" y2="420.3616"/><line style="stroke:#181818;stroke-width:1.0;" x1="312.7221" x2="313.2936" y1="418.1148" y2="428.0984"/><line style="stroke:#181818;stroke-width:1.0;" x1="312.7221" x2="317.88" y1="418.1148" y2="424.23"/><line style="stroke:#181818;stroke-width:1.0;" x1="314.4902" x2="308.375" y1="414.007" y2="419.1649"/><line style="stroke:#181818;stroke-width:1.0;" x1="254.7414" x2="260.8566" y1="355.6666" y2="350.5086"/><line style="stroke:#181818;stroke-width:1.0;" x1="256.6756" x2="262.7908" y1="357.9598" y2="352.8018"/><line style="stroke:#181818;stroke-width:1.0;" x1="260.3779" x2="255.22" y1="356.1452" y2="350.03"/></g><!--MD5=[636c4cbf2bb40ce634cacaf01a62e11c]
28
-link PurchaseDetail to Product--><g id="link_PurchaseDetail_Product"><path codeLine="129" d="M478.21,575.23 C458.75,597.19 438.24,620.32 420.65,640.16 " fill="none" id="PurchaseDetail-Product" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="420.5934" x2="419.7821" y1="640.2105" y2="650.1775"/><line style="stroke:#181818;stroke-width:1.0;" x1="420.5934" x2="410.7979" y1="640.2105" y2="642.2225"/><line style="stroke:#181818;stroke-width:1.0;" x1="420.5934" x2="415.29" y1="640.2105" y2="646.2"/><line style="stroke:#181818;stroke-width:1.0;" x1="424.914" x2="418.9244" y1="641.3648" y2="636.0614"/><line style="stroke:#181818;stroke-width:1.0;" x1="477.9936" x2="483.9831" y1="569.4531" y2="574.7564"/><line style="stroke:#181818;stroke-width:1.0;" x1="476.0048" x2="481.9943" y1="571.6991" y2="577.0025"/><line style="stroke:#181818;stroke-width:1.0;" x1="478.3366" x2="483.64" y1="575.0995" y2="569.11"/></g><!--MD5=[469537f6e6fbfad22558102ade648a2e]
29
-link StockProduct to Product--><g id="link_StockProduct_Product"><path codeLine="130" d="M374.68,568.81 C374.68,585.83 374.68,603.86 374.68,620.72 " fill="none" id="StockProduct-Product" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="374.68" x2="380.68" y1="620.89" y2="628.89"/><line style="stroke:#181818;stroke-width:1.0;" x1="374.68" x2="368.68" y1="620.89" y2="628.89"/><line style="stroke:#181818;stroke-width:1.0;" x1="374.68" x2="374.68" y1="620.89" y2="628.89"/><line style="stroke:#181818;stroke-width:1.0;" x1="378.68" x2="370.68" y1="618.89" y2="618.89"/><line style="stroke:#181818;stroke-width:1.0;" x1="370.68" x2="378.68" y1="564.7" y2="564.7"/><line style="stroke:#181818;stroke-width:1.0;" x1="370.68" x2="378.68" y1="567.7" y2="567.7"/><line style="stroke:#181818;stroke-width:1.0;" x1="374.68" x2="374.68" y1="568.7" y2="560.7"/></g><!--MD5=[5fa2e163e1a5922a0d0ebcb119c05bb7]
30
-link Product to Price--><g id="link_Product_Price"><path codeLine="131" d="M374.68,764.3 C374.68,779.09 374.68,794.73 374.68,809.66 " fill="none" id="Product-Price" style="stroke:#181818;stroke-width:1.0;"/><line style="stroke:#181818;stroke-width:1.0;" x1="378.68" x2="370.68" y1="812.93" y2="812.93"/><line style="stroke:#181818;stroke-width:1.0;" x1="378.68" x2="370.68" y1="809.93" y2="809.93"/><line style="stroke:#181818;stroke-width:1.0;" x1="374.68" x2="374.68" y1="808.93" y2="816.93"/><line style="stroke:#181818;stroke-width:1.0;" x1="370.68" x2="378.68" y1="761" y2="761"/><line style="stroke:#181818;stroke-width:1.0;" x1="370.68" x2="378.68" y1="764" y2="764"/><line style="stroke:#181818;stroke-width:1.0;" x1="374.68" x2="374.68" y1="765" y2="757"/></g><!--MD5=[6ccd130684db3a325492519a433f01fa]
31
-@startuml Database
32
-
33
-entity User {
34
-  * id
35
-  __
36
-  * name
37
-  * username
38
-  * status
39
-  * password
40
-  __
41
-  * role_id
42
-}
43
-
44
-entity Role {
45
-  * id
46
-  __
47
-  * name
48
-}
49
-
50
-entity Customer {
51
-  * id
52
-  __
53
-  * name
54
-  * address
55
-  * phone
56
-  * npwp
57
-}
58
-
59
-entity Product {
60
-  * id
61
-  __
62
-  * number
63
-  * name
64
-  * unit
65
-  * profit
66
-}
67
-
68
-entity Supplier {
69
-  * id
70
-  __
71
-  * name
72
-  * address
73
-  * phone
74
-  * email
75
-  * npwp
76
-}
77
-
78
-entity Purchase {
79
-  * id
80
-  __
81
-  * number
82
-  * status
83
-  __
84
-  * supplier_id
85
-  * user_id
86
-}
87
-
88
-entity Sale {
89
-  * id
90
-  __
91
-  * number
92
-  * status
93
-  __
94
-  * customer_id
95
-  * user_id
96
-}
97
-
98
-entity StockProduct {
99
-  * id
100
-  __
101
-  * purchase_number
102
-  * sale_number
103
-  * qty
104
-  __
105
-  * product_number
106
-}
107
-
108
-entity Price {
109
-  * id
110
-  __
111
-  * price
112
-  __
113
-  * product_number
114
-  * customer_id
115
-  * supplier_id
116
-}
117
-
118
-entity SaleDetail {
119
-  * id
120
-  __
121
-  * price
122
-  * ppn
123
-  * qty
124
-  __
125
-  * sale_number
126
-  * product_number
127
-}
128
-
129
-entity PurchaseDetail {
130
-  * id
131
-  __
132
-  * price
133
-  * ppn
134
-  * qty
135
-  __
136
-  * purchase_number
137
-  * product_number
138
-}
139
-
140
-entity Ppn {
141
-  * id
142
-  __
143
-  * ppn
144
-}
145
-
146
-User ||- -|{ Role
147
-User }|- -|| Purchase
148
-User }|- -|| Sale
149
-Supplier }|- -|| Purchase
150
-Supplier ||- -|| Price
151
-Customer ||- -|{ Sale
152
-Customer ||- -|| Price
153
-Sale ||- -|| SaleDetail
154
-Sale ||- -|| Price
155
-Purchase }|- -|| PurchaseDetail
156
-Purchase ||- -|| Price
157
-Purchase ||- -|{ StockProduct
158
-SaleDetail ||- -|{ Product
159
-Sale ||- -|{ StockProduct
160
-PurchaseDetail ||- -|{ Product
161
-StockProduct ||- -|{ Product
162
-Product ||- -|| Price
163
-@end
164
-
165
-PlantUML version 1.2022.5(Sat Apr 30 17:55:52 WIB 2022)
166
-(GPL source distribution)
167
-Java Runtime: OpenJDK Runtime Environment
168
-JVM: OpenJDK 64-Bit Server VM
169
-Default Encoding: UTF-8
170
-Language: en
171
-Country: US
172
---></g></svg>

+ 2
- 2
resources/js/pages/Purchases/Composables/useProductCart.js Parādīt failu

@@ -1,8 +1,8 @@
1 1
 import FormValidationError from '@/utils/FormValidationError'
2 2
 import { reactive } from 'vue'
3 3
 
4
-export function useProductCart(form, initialProducts) {
5
-  const productCart = reactive([])
4
+export function useProductCart(form, initialProducts = []) {
5
+  const productCart = reactive(initialProducts)
6 6
 
7 7
   const productValidation = () => {
8 8
     const existProduct = productCart.find(

+ 203
- 2
resources/js/pages/Purchases/Edit.vue Parādīt failu

@@ -1,9 +1,210 @@
1 1
 <script setup>
2
+import { optionStatus } from './config'
3
+import { cartTable } from './config'
4
+import Details from './Components/Details.vue'
5
+import Cart from './Components/Cart.vue'
6
+import { useProductCart } from './Composables/useProductCart'
7
+import { onShowDialog } from './Composables/onShowDialog'
8
+import { useForm } from '@/composables/useForm'
9
+import AppInputText from '@/components/AppInputText.vue'
10
+import AppInputNumber from '@/components/AppInputNumber.vue'
11
+import AppDropdown from '@/components/AppDropdown.vue'
12
+import AppAutoComplete from '@/components/AppAutoComplete.vue'
2 13
 import DashboardLayout from '@/layouts/Dashboard/DashboardLayout.vue'
14
+
15
+const props = defineProps({
16
+  id: Number,
17
+  number: String,
18
+  ppn: Number,
19
+  ppnChecked: Boolean,
20
+  supplier: Object,
21
+  products: {
22
+    type: Array,
23
+    default: [],
24
+  },
25
+  purchaseDetail: Array,
26
+})
27
+
28
+const form = useForm({
29
+  status: 'pending',
30
+  price: null,
31
+  qty: null,
32
+  supplier: props.supplier,
33
+  product: null,
34
+  ppn: props.ppn,
35
+  checkedPpn: props.ppnChecked,
36
+})
37
+
38
+const onSubmit = () => {
39
+  form
40
+    .transform((data) => ({
41
+      status: data.status,
42
+      ppn: data.checkedPpn,
43
+      products: productCart,
44
+    }))
45
+    .put(route('purchases.update', props.id))
46
+}
47
+
48
+const {
49
+  productCart,
50
+  onAddProduct,
51
+  onDeleteProduct,
52
+  onEditProduct,
53
+  totalProductPrice,
54
+} = useProductCart(form, props.purchaseDetail)
55
+
56
+const { onShowCreateProduct } = onShowDialog()
3 57
 </script>
4 58
 
5 59
 <template>
6
-  <DashboardLayout title="Detail Pembelian">
7
-    <h1>Soon</h1>
60
+  <DashboardLayout title="Tambah Pembelian">
61
+    <DynamicDialog />
62
+
63
+    <div class="grid">
64
+      <div class="col-12 md:col-8">
65
+        <div class="grid">
66
+          <div class="col-12">
67
+            <Card>
68
+              <template #title> Pembeli </template>
69
+              <template #content>
70
+                <div class="grid">
71
+                  <div class="col-12 md:col-6">
72
+                    <AppDropdown
73
+                      label="Status"
74
+                      placeholder="status"
75
+                      :options="optionStatus"
76
+                      :error="form.errors.status"
77
+                      v-model="form.status"
78
+                    />
79
+                  </div>
80
+
81
+                  <div class="col-12 md:col-6">
82
+                    <AppInputText
83
+                      disabled
84
+                      label="Supplier"
85
+                      placeholder="supplier"
86
+                      v-model="supplier.name"
87
+                    />
88
+                  </div>
89
+                </div>
90
+              </template>
91
+            </Card>
92
+          </div>
93
+
94
+          <div class="col-12">
95
+            <Card>
96
+              <template #title>Produk</template>
97
+              <template #content>
98
+                <div class="grid">
99
+                  <div class="col-12 md:col-6">
100
+                    <AppAutoComplete
101
+                      :disabled="!form.supplier?.id"
102
+                      empty
103
+                      label="Produk"
104
+                      placeholder="produk"
105
+                      field="name"
106
+                      refresh-data="products"
107
+                      v-model="form.product"
108
+                      :error="form.errors.product"
109
+                      :suggestions="products"
110
+                    >
111
+                      <template #item="slotProps">
112
+                        <template v-if="slotProps.item">
113
+                          <div class="flex flex-column">
114
+                            <span>{{ slotProps.item.number }}</span>
115
+                            <span>{{ slotProps.item.name }}</span>
116
+                          </div>
117
+                        </template>
118
+                      </template>
119
+
120
+                      <template #empty>
121
+                        <span
122
+                          class="cursor-pointer"
123
+                          style="color: var(--primary-color)"
124
+                          @click="onShowCreateProduct"
125
+                        >
126
+                          Tambah Produk
127
+                        </span>
128
+                      </template>
129
+                    </AppAutoComplete>
130
+                  </div>
131
+
132
+                  <div v-if="form.product?.unit" class="col-12 md:col-6">
133
+                    <AppInputText
134
+                      disabled
135
+                      label="Satuan"
136
+                      placeholder="satuan"
137
+                      v-model="form.product.unit"
138
+                    />
139
+                  </div>
140
+
141
+                  <div class="col-12 md:col-6">
142
+                    <AppInputNumber
143
+                      :disabled="!form.supplier?.id"
144
+                      label="Harga"
145
+                      placeholder="harga"
146
+                      v-model="form.price"
147
+                    />
148
+                  </div>
149
+
150
+                  <div class="col-12 md:col-6">
151
+                    <AppInputText
152
+                      :disabled="!form.supplier?.id"
153
+                      label="Kuantitas"
154
+                      placeholder="kuantitas"
155
+                      type="number"
156
+                      v-model="form.qty"
157
+                    />
158
+                  </div>
159
+                </div>
160
+              </template>
161
+              <template #footer>
162
+                <div class="flex flex-column md:flex-row justify-content-end">
163
+                  <Button
164
+                    label="Tambah Produk"
165
+                    icon="pi pi-check"
166
+                    class="p-button-outlined"
167
+                    :disabled="
168
+                      !form.price || !form.qty || !form.product?.number
169
+                    "
170
+                    @click="onAddProduct"
171
+                  />
172
+                </div>
173
+              </template>
174
+            </Card>
175
+          </div>
176
+
177
+          <div class="col-12">
178
+            <Cart
179
+              title="Keranjang Produk"
180
+              :value-table="productCart"
181
+              :header-table="cartTable"
182
+              v-model:checked-ppn="form.checkedPpn"
183
+              @delete="onDeleteProduct"
184
+              @edit="onEditProduct"
185
+            />
186
+          </div>
187
+        </div>
188
+      </div>
189
+
190
+      <div class="col-12 md:col-4">
191
+        <Details
192
+          title="Detail Pembelian"
193
+          message="Pastikan semua produk sudah benar"
194
+          :number="number"
195
+          :status="form.status"
196
+          :person="form.supplier"
197
+          :product="form.product"
198
+          :price="totalProductPrice()"
199
+          :disabled="
200
+            form.processing ||
201
+            !form.status ||
202
+            !form.supplier?.id ||
203
+            productCart.length === 0
204
+          "
205
+          @submit="onSubmit"
206
+        />
207
+      </div>
208
+    </div>
8 209
   </DashboardLayout>
9 210
 </template>