Skip to content

Commit ff496c2

Browse files
authored
Merge pull request #1396 from Blair2004/v4.8.x-remix
V4.8.x remix
2 parents f90b14c + c56bc52 commit ff496c2

File tree

8 files changed

+378
-74
lines changed

8 files changed

+378
-74
lines changed

app/Crud/ExpenseCrud.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,16 @@ public function getForm( $entry = null )
222222
'value' => 'x_after_month_starts',
223223
],
224224
],
225-
'name' => 'occurence',
225+
'name' => 'occurrence',
226226
'label' => __( 'Occurrence' ),
227227
'description' => __( 'Define how often this expenses occurs' ),
228-
'value' => $entry->occurence ?? '',
228+
'value' => $entry->occurrence ?? '',
229229
], [
230230
'type' => 'text',
231-
'name' => 'occurence_value',
231+
'name' => 'occurrence_value',
232232
'label' => __( 'Occurrence Value' ),
233233
'description' => __( 'Must be used in case of X days after month starts and X days before month ends.' ),
234-
'value' => $entry->occurence_value ?? '',
234+
'value' => $entry->occurrence_value ?? '',
235235
], [
236236
'type' => 'textarea',
237237
'name' => 'description',
@@ -406,7 +406,7 @@ public function getColumns()
406406
'$direction' => '',
407407
'$sort' => false,
408408
],
409-
'occurence' => [
409+
'occurrence' => [
410410
'label' => __( 'Occurrence' ),
411411
'$direction' => '',
412412
'$sort' => false,
@@ -432,18 +432,18 @@ public function setActions( CrudEntry $entry, $namespace )
432432
$entry->value = (string) ns()->currency->value( $entry->value );
433433
$entry->recurring = (bool) $entry->recurring ? __( 'Yes' ) : __( 'No' );
434434

435-
switch ( $entry->occurence ) {
436-
case 'month_start' : $entry->occurence = __( 'Month Starts' );
435+
switch ( $entry->occurrence ) {
436+
case 'month_start' : $entry->occurrence = __( 'Month Starts' );
437437
break;
438-
case 'month_mid' : $entry->occurence = __( 'Month Middle' );
438+
case 'month_mid' : $entry->occurrence = __( 'Month Middle' );
439439
break;
440-
case 'month_end' : $entry->occurence = __( 'Month Ends' );
440+
case 'month_end' : $entry->occurrence = __( 'Month Ends' );
441441
break;
442-
case 'x_after_month_starts' : $entry->occurence = __( 'X Days Before Month Starts' );
442+
case 'x_after_month_starts' : $entry->occurrence = __( 'X Days Before Month Starts' );
443443
break;
444-
case 'x_before_month_ends' : $entry->occurence = __( 'X Days Before Month Ends' );
444+
case 'x_before_month_ends' : $entry->occurrence = __( 'X Days Before Month Ends' );
445445
break;
446-
default: $entry->occurence = __( 'Unknown Occurrence' );
446+
default: $entry->occurrence = __( 'Unknown Occurrence' );
447447
break;
448448
}
449449

app/Services/ExpenseService.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ public function handleRecurringExpenses()
416416
->active()
417417
->get()
418418
->map( function( $expense ) {
419-
switch ( $expense->occurence ) {
419+
switch ( $expense->occurrence ) {
420420
case 'month_starts':
421421
$expenseScheduledDate = Carbon::parse( $this->dateService->copy()->startOfMonth() );
422422
break;
@@ -427,10 +427,10 @@ public function handleRecurringExpenses()
427427
$expenseScheduledDate = Carbon::parse( $this->dateService->copy()->endOfMonth() );
428428
break;
429429
case 'x_before_month_ends':
430-
$expenseScheduledDate = Carbon::parse( $this->dateService->copy()->endOfMonth()->subDays( $expense->occurence_value ) );
430+
$expenseScheduledDate = Carbon::parse( $this->dateService->copy()->endOfMonth()->subDays( $expense->occurrence_value ) );
431431
break;
432432
case 'x_after_month_starts':
433-
$expenseScheduledDate = Carbon::parse( $this->dateService->copy()->startOfMonth()->addDays( $expense->occurence_value ) );
433+
$expenseScheduledDate = Carbon::parse( $this->dateService->copy()->startOfMonth()->addDays( $expense->occurrence_value ) );
434434
break;
435435
}
436436

app/Services/OrdersService.php

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function create( $fields, Order $order = null )
117117
* check discount validity and throw an
118118
* error is something is not set correctly.
119119
*/
120-
$this->__checkDiscountVality( $fields );
120+
$this->__checkDiscountValidity( $fields );
121121

122122
/**
123123
* check delivery informations before
@@ -150,7 +150,7 @@ public function create( $fields, Order $order = null )
150150
/**
151151
* if we're editing an order. We need to loop the products in order
152152
* to recover all the products that has been deleted from the POS and therefore
153-
* aren't tracked no more.
153+
* aren't tracked no more. This also make stock adjustment for product which has changed.
154154
*/
155155
$this->__deleteUntrackedProducts( $order, $fields[ 'products' ] );
156156

@@ -486,9 +486,8 @@ public function __deleteUntrackedProducts( $order, $products )
486486
{
487487
if ( $order instanceof Order ) {
488488
$ids = collect( $products )
489-
->filter( fn( $product ) => isset( $product[ 'id' ] ) )
490-
->map( fn( $product ) => $product[ 'id' ] . '-' . $product[ 'unit_id' ] ?? false )
491-
->filter( fn( $product ) => $product !== false )
489+
->filter( fn( $product ) => isset( $product[ 'id' ] ) && isset( $product[ 'unit_id' ] ) )
490+
->map( fn( $product ) => $product[ 'id' ] . '-' . $product[ 'unit_id' ] )
492491
->toArray();
493492

494493
/**
@@ -498,34 +497,44 @@ public function __deleteUntrackedProducts( $order, $products )
498497
*/
499498
if ( $order->payment_status !== Order::PAYMENT_HOLD ) {
500499
$order->products->map( function( OrderProduct $product ) use ( $products ) {
501-
$products = collect( $products )
502-
->filter( fn( $product ) => isset( $product[ 'id' ] ) )
503-
->mapWithKeys( fn( $product ) => [ $product[ 'id' ] => $product ] )
504-
->toArray();
505-
506-
if ( in_array( $product->id, array_keys( $products ) ) ) {
507-
if ( $product->quantity < $products[ $product->id ][ 'quantity' ] ) {
508-
return [
509-
'operation' => 'add',
510-
'unit_price' => $products[ $product->id ][ 'unit_price' ],
511-
'total_price' => $products[ $product->id ][ 'total_price' ],
512-
'quantity' => $products[ $product->id ][ 'quantity' ] - $product->quantity,
513-
'orderProduct' => $product,
514-
];
515-
} elseif ( $product->quantity > $products[ $product->id ][ 'quantity' ] ) {
516-
return [
517-
'operation' => 'remove',
518-
'unit_price' => $products[ $product->id ][ 'unit_price' ],
519-
'total_price' => $products[ $product->id ][ 'total_price' ],
520-
'quantity' => $product->quantity - $products[ $product->id ][ 'quantity' ],
521-
'orderProduct' => $product,
522-
];
500+
$productHistory = ProductHistory::where( 'operation_type', ProductHistory::ACTION_SOLD )
501+
->where( 'order_product_id', $product->id )
502+
->first();
503+
504+
/**
505+
* We should restore or retreive quantities when the
506+
* product has initially be marked as sold.
507+
*/
508+
if ( $productHistory instanceof ProductHistory ) {
509+
$products = collect( $products )
510+
->filter( fn( $product ) => isset( $product[ 'id' ] ) )
511+
->mapWithKeys( fn( $product ) => [ $product[ 'id' ] => $product ] )
512+
->toArray();
513+
514+
if ( in_array( $product->id, array_keys( $products ) ) ) {
515+
if ( $product->quantity < $products[ $product->id ][ 'quantity' ] ) {
516+
return [
517+
'operation' => 'add',
518+
'unit_price' => $products[ $product->id ][ 'unit_price' ],
519+
'total_price' => $products[ $product->id ][ 'total_price' ],
520+
'quantity' => $products[ $product->id ][ 'quantity' ] - $product->quantity,
521+
'orderProduct' => $product,
522+
];
523+
} elseif ( $product->quantity > $products[ $product->id ][ 'quantity' ] ) {
524+
return [
525+
'operation' => 'remove',
526+
'unit_price' => $products[ $product->id ][ 'unit_price' ],
527+
'total_price' => $products[ $product->id ][ 'total_price' ],
528+
'quantity' => $product->quantity - $products[ $product->id ][ 'quantity' ],
529+
'orderProduct' => $product,
530+
];
531+
}
523532
}
524533
}
525534

526535
/**
527-
* when to change has been made on
528-
* the order product
536+
* When no changes has been made
537+
* on the orde product.
529538
*/
530539
return false;
531540
})
@@ -626,7 +635,7 @@ private function __getShippingFee($fields): float
626635
*
627636
* @throws NotAllowedException
628637
*/
629-
public function __checkDiscountVality( $fields )
638+
public function __checkDiscountValidity( $fields )
630639
{
631640
if (! empty(@$fields['discount_type'])) {
632641
if ($fields['discount_type'] === 'percentage' && (floatval($fields['discount_percentage']) < 0) || (floatval($fields['discount_percentage']) > 100)) {
@@ -1035,15 +1044,12 @@ private function __saveOrderProducts($order, $products)
10351044

10361045
$orderProducts = $products->map(function ($product) use (&$subTotal, &$taxes, &$order, &$gross) {
10371046

1038-
$previousQuantity = 0;
1039-
10401047
/**
10411048
* if the product id is provided
10421049
* then we can use that id as a reference.
10431050
*/
10441051
if ( isset( $product[ 'id' ] ) ) {
10451052
$orderProduct = OrderProduct::find( $product[ 'id' ] );
1046-
$previousQuantity = $orderProduct->quantity;
10471053
} else {
10481054
$orderProduct = new OrderProduct;
10491055
}
@@ -1124,10 +1130,13 @@ private function __saveOrderProducts($order, $products)
11241130
* already exists and which are edited. We'll here only records
11251131
* products that doesn't exists yet.
11261132
*/
1127-
if ( $orderProduct->wasRecentlyCreated ) {
1133+
$stockHistoryExists = ProductHistory::where( 'order_product_id', $orderProduct->id )
1134+
->where( 'operation_type', ProductHistory::ACTION_SOLD )
1135+
->count() === 1;
1136+
1137+
if ( ! $stockHistoryExists ) {
11281138
$this->productService->stockAdjustment( ProductHistory::ACTION_SOLD, $history );
11291139
}
1130-
11311140
}
11321141

11331142
event( new OrderProductAfterSavedEvent( $orderProduct, $order, $product ) );
@@ -1150,11 +1159,11 @@ private function __buildOrderProducts( $products )
11501159
$product = null;
11511160
$productUnitQuantity = null;
11521161

1153-
if ( ! empty( $orderProduct[ 'sku' ] ) || ! empty( $orderProduct[ 'product_id' ] ) ) {
1162+
if ( ! empty( $orderProduct[ 'sku' ] ?? null ) || ! empty( $orderProduct[ 'product_id' ] ?? null ) ) {
11541163
$product = Cache::remember( 'store-' . ( $orderProduct['product_id'] ?? $orderProduct['sku'] ), 60, function() use ($orderProduct) {
1155-
if (! empty(@$orderProduct['product_id'])) {
1164+
if ( ! empty( $orderProduct['product_id'] ?? null ) ) {
11561165
return $this->productService->get($orderProduct['product_id']);
1157-
} elseif (! empty(@$orderProduct['sku'])) {
1166+
} elseif ( ! empty( $orderProduct['sku'] ?? null ) ) {
11581167
return $this->productService->getProductUsingSKUOrFail($orderProduct['sku']);
11591168
}
11601169
});
@@ -1298,14 +1307,24 @@ public function checkQuantityAvailability( $product, $productUnitQuantity, $orde
12981307
* we want to deduct from the stock, we need to know wether the quantity has changed (greater or not). We then need to pull
12991308
* the original reference of the orderProduct to compute the new quantity that will be deducted from inventory.
13001309
*/
1310+
$quantityToIgnore = 0;
1311+
13011312
if ( isset( $orderProduct[ 'id' ] ) ) {
1302-
$orderProductRerefence = OrderProduct::find( $orderProduct[ 'id' ] );
1303-
$orderProductQuantity = $this->mathService->set( $orderProductRerefence->quantity )
1304-
->minus( $orderProduct[ 'quantity' ] )
1305-
->toFloat();
1313+
$stockWasDeducted = ProductHistory::where( 'order_product_id', $orderProduct[ 'id' ] )
1314+
->where( 'operation_type', ProductHistory::ACTION_SOLD )
1315+
->count() === 1;
1316+
1317+
/**
1318+
* Only when the stock was deducted, we'll ignore the quantity
1319+
* that is currently in use by the order product.
1320+
*/
1321+
if ( $stockWasDeducted ) {
1322+
$orderProductRerefence = OrderProduct::find( $orderProduct[ 'id' ] );
1323+
$quantityToIgnore = $orderProductRerefence->quantity;
1324+
}
13061325
}
13071326

1308-
if ( $productUnitQuantity->quantity - $storageQuantity < abs( $orderProductQuantity ) ) {
1327+
if ( ( $productUnitQuantity->quantity + $quantityToIgnore ) - $storageQuantity < abs( $orderProductQuantity ) ) {
13091328
throw new \Exception(
13101329
sprintf(
13111330
__( 'Unable to proceed, there is not enough stock for %s using the unit %s. Requested : %s, available %s' ),

database/migrations/create/2020_06_20_000000_create_expenses_table.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ public function up()
2727
$table->boolean( 'recurring' )->default(false);
2828
$table->boolean( 'active' )->default(false);
2929
$table->integer( 'group_id' )->nullable();
30-
$table->string( 'occurence' )->nullable(); // 1st 15th startOfMonth, endOfMonth
31-
$table->string( 'occurence_value' )->nullable(); // 1st 15th startOfMonth, endOfMonth
30+
$table->string( 'occurrence' )->nullable(); // 1st 15th startOfMonth, endOfMonth
31+
$table->string( 'occurrence_value' )->nullable(); // 1st 15th startOfMonth, endOfMonth
3232
$table->integer( 'author' );
3333
$table->string( 'uuid' )->nullable();
3434
$table->timestamps();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
use App\Classes\Schema;
4+
use Illuminate\Database\Migrations\Migration;
5+
use Illuminate\Database\Schema\Blueprint;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
if ( Schema::hasTable( 'nexopos_expenses' ) ) {
17+
Schema::table( 'nexopos_expenses', function( Blueprint $table ) {
18+
if ( Schema::hasColumn( 'nexopos_expenses', 'occurence' ) ) {
19+
$table->renameColumn( 'occurence', 'occurrence' );
20+
}
21+
if ( Schema::hasColumn( 'nexopos_expenses', 'occurence_value' ) ) {
22+
$table->renameColumn( 'occurence_value', 'occurrence_value' );
23+
}
24+
});
25+
}
26+
}
27+
28+
/**
29+
* Reverse the migrations.
30+
*
31+
* @return void
32+
*/
33+
public function down()
34+
{
35+
//
36+
}
37+
};

tests/Feature/CreateOrderTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ public function testCreateAndEditOrderByDeductedGreaterQuantity()
4242
$this->attemptCreateAndEditOrderWithGreaterQuantity();
4343
}
4444

45+
public function testHoldAndCheckoutOrder()
46+
{
47+
$this->attemptAuthenticate();
48+
$this->attemptHoldAndCheckoutOrder();
49+
}
50+
51+
public function testHoldAndCheckoutOrderWithGroupedProducts()
52+
{
53+
$this->attemptAuthenticate();
54+
$this->attemptHoldOrderAndCheckoutWithGroupedProducts();
55+
}
56+
4557
public function testDeletedVoidedOrder()
4658
{
4759
$this->attemptAuthenticate();

tests/Traits/WithExpenseTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ protected function attemptCreateExpenses()
9898
'value' => 1500,
9999
'recurring' => false,
100100
'category_id' => $category->id,
101-
'occurence' => 'month_starts',
101+
'occurrence' => 'month_starts',
102102
'group_id' => $role->id,
103103
],
104104
]);

0 commit comments

Comments
 (0)