瀏覽代碼

fix: sale master

Muhammad Iqbal Afandi 3 年之前
父節點
當前提交
31530dfbd9

+ 1
- 0
app/Http/Controllers/SalesController.php 查看文件

@@ -77,6 +77,7 @@ class SalesController extends Controller
77 77
                             "ppn" => $stockProduct->ppn,
78 78
                             "qty" => $stockProduct->qty,
79 79
                             "unit" => $stockProduct->product->unit,
80
+                            "profit" => $stockProduct->product->profit,
80 81
                         ]
81 82
                     )
82 83
             ),

+ 1
- 0
resources/js/components/AppPassword.vue 查看文件

@@ -53,6 +53,7 @@ const ariaDescribedbyLabel = computed(
53 53
     <Password
54 54
       class="w-full"
55 55
       input-class="w-full"
56
+      :class="{ 'p-invalid': isError }"
56 57
       :promptLabel="promptLabel"
57 58
       :weakLabel="weakLabel"
58 59
       :mediumLabel="mediumLabel"

+ 1
- 1
resources/js/pages/Sales/Components/Cart.vue 查看文件

@@ -1,6 +1,6 @@
1 1
 <script setup>
2 2
 import { ref } from 'vue'
3
-import { IDRCurrencyFormat } from '@/utils/currencyFormat'
3
+import { IDRCurrencyFormat } from '@/utils/helpers'
4 4
 import AppInputNumber from '@/components/AppInputNumber.vue'
5 5
 import AppInputText from '@/components/AppInputText.vue'
6 6
 

+ 1
- 1
resources/js/pages/Sales/Components/Details.vue 查看文件

@@ -1,5 +1,5 @@
1 1
 <script setup>
2
-import { IDRCurrencyFormat } from '@/utils/currencyFormat'
2
+import { IDRCurrencyFormat } from '@/utils/helpers'
3 3
 
4 4
 defineProps({
5 5
   title: String,

resources/js/pages/Sales/Composables/onShowDialog.js → resources/js/pages/Sales/Composables/useDialog.js 查看文件

@@ -1,8 +1,8 @@
1
-import { useDialog } from 'primevue/usedialog'
1
+import { useDialog as usePrimeDialog } from 'primevue/usedialog'
2 2
 import CustomerCreate from '../Components/CustomerCreate.vue'
3 3
 
4
-export function onShowDialog() {
5
-  const dialog = useDialog()
4
+export function useDialog() {
5
+  const dialog = usePrimeDialog()
6 6
 
7 7
   const dialogStyle = {
8 8
     style: {

+ 49
- 17
resources/js/pages/Sales/Composables/useProductCart.js 查看文件

@@ -1,39 +1,63 @@
1 1
 import { reactive } from 'vue'
2
-import FormValidationError from '@/utils/FormValidationError'
2
+import { FormValidationError } from '@/utils/helpers'
3 3
 
4 4
 export function useProductCart(form, initialProducts = []) {
5 5
   const productCart = reactive(initialProducts)
6 6
 
7 7
   const productCartDeleted = reactive([])
8 8
 
9
+  const productErrors = reactive([])
10
+
9 11
   const productValidation = () => {
10
-    const existProduct = productCart.find(
11
-      (product) => product.number === form.product.number
12
-    )
12
+    onClearProductErrors()
13
+
14
+    productCart.find((product) => {
15
+      if (product.number === form.product.number) {
16
+        // productErrors.push({
17
+        //   message: 'Produk sudah ada dikeranjang',
18
+        //   field: 'product',
19
+        // })
20
+
21
+        if (form.qty + product.qty > form.product.qty) {
22
+          productErrors.push({
23
+            message: 'Stok tidak mencukupi',
24
+            field: 'qty',
25
+          })
26
+        }
27
+      }
28
+    })
13 29
 
14
-    if (existProduct) {
15
-      throw new FormValidationError('Produk sudah ada dikeranjang', 'product')
30
+    if (productErrors.length) {
31
+      throw new FormValidationError('form error', productErrors)
16 32
     }
17 33
   }
18 34
 
19 35
   const onAddProduct = () => {
20 36
     try {
21
-      form.clearErrors('product', 'price', 'qty')
37
+      form.clearErrors('product', 'qty')
22 38
 
23 39
       productValidation()
24 40
 
25
-      productCart.push({
26
-        label: 'add',
27
-        number: form.product.number,
28
-        name: form.product.name,
29
-        price: form.price,
30
-        qty: form.qty,
31
-        unit: form.product.unit,
41
+      productCart.find((product) => {
42
+        if (product.number === form.product.number) {
43
+          product.qty += form.qty
44
+        } else {
45
+          productCart.push({
46
+            label: 'add',
47
+            number: form.product.number,
48
+            name: form.product.name,
49
+            price: form.price,
50
+            qty: form.qty,
51
+            unit: form.product.unit,
52
+          })
53
+        }
32 54
       })
33 55
 
34
-      form.reset('product', 'price', 'qty')
56
+      form.reset('product', 'qty')
35 57
     } catch (e) {
36
-      form.setError(e.field, e.message)
58
+      e.errors.forEach((error) => {
59
+        form.setError(error.field, error.message)
60
+      })
37 61
     }
38 62
   }
39 63
 
@@ -56,6 +80,10 @@ export function useProductCart(form, initialProducts = []) {
56 80
     productCartDeleted.splice(0)
57 81
   }
58 82
 
83
+  const onClearProductErrors = () => {
84
+    productErrors.splice(0)
85
+  }
86
+
59 87
   const totalProductPrice = () => {
60 88
     const productPrices = productCart.map((product) => {
61 89
       if (form.checkedPpn) {
@@ -65,7 +93,10 @@ export function useProductCart(form, initialProducts = []) {
65 93
       }
66 94
     })
67 95
 
68
-    return productPrices.reduce((prev, current) => prev + current, 0)
96
+    return productPrices.reduce(
97
+      (prevPrice, currentPrice) => prevPrice + currentPrice,
98
+      0
99
+    )
69 100
   }
70 101
 
71 102
   const onEditProduct = (event) => {
@@ -80,6 +111,7 @@ export function useProductCart(form, initialProducts = []) {
80 111
   return {
81 112
     productCart,
82 113
     productCartDeleted,
114
+    productErrors,
83 115
     onClearProductCart,
84 116
     onClearProductCartDelete,
85 117
     onAddProduct,

+ 27
- 10
resources/js/pages/Sales/Create.vue 查看文件

@@ -1,11 +1,12 @@
1 1
 <script setup>
2
-import { computed } from 'vue'
2
+import { computed, watchEffect } from 'vue'
3
+import { profit } from '@/utils/helpers'
3 4
 import { optionStatus } from './config'
4 5
 import { cartTable } from './config'
5 6
 import Details from './Components/Details.vue'
6 7
 import Cart from './Components/Cart.vue'
7 8
 import { useProductCart } from './Composables/useProductCart'
8
-import { onShowDialog } from './Composables/onShowDialog'
9
+import { useDialog } from './Composables/useDialog'
9 10
 import { useForm } from '@/composables/useForm'
10 11
 import AppInputText from '@/components/AppInputText.vue'
11 12
 import AppInputNumber from '@/components/AppInputNumber.vue'
@@ -54,20 +55,34 @@ const onSubmit = () => {
54 55
     })
55 56
 }
56 57
 
58
+watchEffect(() => {
59
+  if (form.product?.number) {
60
+    form.price = profit(form.product.price, form.product.profit)
61
+
62
+    form.qty = 1
63
+  }
64
+})
65
+
57 66
 const dropdownStatus = computed(() => {
58 67
   return optionStatus.filter((val) => val.value != 'pending')
59 68
 })
60 69
 
70
+const profitDescription = computed(() => {
71
+  const priceProfit = profit(form.product?.price, form.product?.profit)
72
+
73
+  return form.price === priceProfit ? true : false
74
+})
75
+
61 76
 const {
62 77
   productCart,
78
+  productErrors,
63 79
   onAddProduct,
64 80
   onClearProductCart,
65 81
   onDeleteProduct,
66
-  onEditProduct,
67 82
   totalProductPrice,
68 83
 } = useProductCart(form)
69 84
 
70
-const { onShowCustomerCreate } = onShowDialog()
85
+const { onShowCustomerCreate } = useDialog()
71 86
 </script>
72 87
 
73 88
 <template>
@@ -142,7 +157,7 @@ const { onShowCustomerCreate } = onShowDialog()
142 157
                       field="name"
143 158
                       refresh-data="stockProducts"
144 159
                       v-model="form.product"
145
-                      :error="form.errors.products"
160
+                      :error="form.errors.product"
146 161
                       :suggestions="stockProducts"
147 162
                     >
148 163
                       <template #item="slotProps">
@@ -202,22 +217,23 @@ const { onShowCustomerCreate } = onShowDialog()
202 217
                   <div class="col-12 md:col-6">
203 218
                     <AppInputNumber
204 219
                       class="m-0"
205
-                      :disabled="!form.customer?.id"
220
+                      :disabled="!form.product?.number"
206 221
                       label="Harga Jual"
207 222
                       placeholder="harga jual"
208 223
                       v-model="form.price"
209 224
                     />
210
-                    <span v-if="form.product?.number" class="text-xs">
211
-                      Sudah termasuk profit 30%
225
+                    <span v-if="profitDescription" class="text-xs">
226
+                      Sudah termasuk profit {{ form.product.profit }} %
212 227
                     </span>
213 228
                   </div>
214 229
 
215 230
                   <div class="col-12 md:col-6">
216 231
                     <AppInputText
217
-                      :disabled="!form.customer?.id"
232
+                      :disabled="!form.product?.number"
218 233
                       label="Kuantitas"
219 234
                       placeholder="kuantitas"
220 235
                       type="number"
236
+                      :error="form.errors.qty"
221 237
                       v-model="form.qty"
222 238
                     />
223 239
                   </div>
@@ -229,6 +245,7 @@ const { onShowCustomerCreate } = onShowDialog()
229 245
                     label="Tambah Produk"
230 246
                     icon="pi pi-check"
231 247
                     class="p-button-outlined"
248
+                    :class="{ 'p-button-danger': productErrors.length }"
232 249
                     :disabled="
233 250
                       !form.price || !form.qty || !form.product?.number
234 251
                     "
@@ -244,9 +261,9 @@ const { onShowCustomerCreate } = onShowDialog()
244 261
               title="Keranjang Produk"
245 262
               :product-cart="productCart"
246 263
               :header-table="cartTable"
264
+              :btn-edit-show="false"
247 265
               v-model:checked-ppn="form.checkedPpn"
248 266
               @delete="onDeleteProduct"
249
-              @edit="onEditProduct"
250 267
             />
251 268
           </div>
252 269
         </div>

+ 30
- 0
resources/js/utils/helpers.js 查看文件

@@ -0,0 +1,30 @@
1
+export function ppn(price, percent) {
2
+  return price + price * (percent / 100)
3
+}
4
+
5
+export function profit(price, percent) {
6
+  return ppn(price, percent)
7
+}
8
+
9
+export function discount(price, percent) {
10
+  return price - price * (percent / 100)
11
+}
12
+
13
+export const IDRCurrencyFormat = (number, decimal = false) => {
14
+  if (number === null) {
15
+    return
16
+  }
17
+
18
+  if (decimal) {
19
+    return 'Rp' + number.toLocaleString('id') + ',00'
20
+  } else {
21
+    return 'Rp' + number.toLocaleString('id')
22
+  }
23
+}
24
+
25
+export class FormValidationError extends Error {
26
+  constructor(message, errors) {
27
+    super(message)
28
+    this.errors = errors
29
+  }
30
+}