CashController::showHistory()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 10
rs 9.4285
cc 2
eloc 6
nc 2
nop 0
1
<?php namespace App\Http\Controllers;
2
3
use App\Exceptions\RepositoryException;
4
use App\Repositories\SnapshotDetailsRepository;
5
use App\Repositories\SnapshotRepository;
6
use Carbon\Carbon;
7
use Response;
8
use Input;
9
use DB;
10
use Redirect;
11
use Validator;
12
13
class CashController extends Controller
14
{
15
16
    private $snapshotRepository;
17
18
    private $detailsRepository;
19
20
    public function __construct(SnapshotRepository $repository, SnapshotDetailsRepository $detailsRepository)
21
    {
22
        $this->snapshotRepository = $repository;
23
        $this->detailsRepository = $detailsRepository;
24
    }
25
26
    public function dashboard($requestedSnapshot = null)
27
    {
28
        if (isset($requestedSnapshot))     // Search snapshot in history
29
        {
30
            $snapshot = $this->snapshotRepository->get($requestedSnapshot);
31
        } else    // Grab the current snapshot, or redirect if no one exists
32
        {
33
            try {
34
                $snapshot = $this->snapshotRepository->current();
35
            } catch (RepositoryException $e) {
36
                if ($e->getCode() == RepositoryException::RESOURCE_NOT_FOUND) {
37
                    return view('cash.init');
38
                }
39
40
                App::abort(500);
41
            }
42
        }
43
44
        $snapshotDetails = $this->detailsRepository->fromSnapshot($snapshot->cs_id);
45
        $allSnapshots = $this->snapshotRepository->all();
46
47
        $cashArray = [floatval($snapshot->amount)];
48
        $lastAmount = $snapshot->amount;
49
50
        $lastOperation = 0;
51
        $cashBySales = 0;
52
        $salesCount = 0;
53
        $operationsCount = 0;
54
55
        foreach ($snapshotDetails as $detail) {
56
57
            $lastAmount += $detail->sum;
58
            array_push($cashArray, $lastAmount);
59
60
            if ($detail->type == 'CASH') {
61
                $lastOperation = $detail->sum;
62
                $operationsCount++;
63
            }
64
65
            if ($detail->type == 'SALE') {
66
                $cashBySales += $detail->sum;
67
                $salesCount++;
68
            }
69
        }
70
71
        // Enough data for current snapshot,
72
        // return all data to the view
73
        if (!$snapshot->is_closed) {
74
            return view('cash.app')->with('snapshot', $snapshot)
75
                ->with('details', $snapshotDetails)
76
                ->with('amounts', $cashArray)
77
                ->with('lastOperation', $lastOperation)
78
                ->with('cashBySales', $cashBySales)
79
                ->with('allSnapshots', $allSnapshots)
80
                ->with('salesCount', $salesCount)
81
                ->with('operationsCount', $operationsCount);
82
        }
83
84
        // Other statistics for closed snapshot
85
86
        $nextSnapshot = $this->snapshotRepository->getNext($snapshot->cs_id);
87
88
        $snapshotTime = new Carbon($snapshot->time);
89
        $nextSnapshotTime = new Carbon($nextSnapshot->time);
90
        $duration = $this->approximateDuration($snapshotTime, $nextSnapshotTime);
91
92
        $delta = $nextSnapshot->amount - $snapshot->predicted_amount;
93
94
        return view('cash.app')->with('snapshot', $snapshot)
95
            ->with('details', $snapshotDetails)
96
            ->with('amounts', $cashArray)
97
            ->with('cashBySales', $cashBySales)
98
            ->with('allSnapshots', $allSnapshots)
99
            ->with('salesCount', $salesCount)
100
            ->with('operationsCount', $operationsCount)
101
            ->with('delta', $delta)
102
            ->with('duration', $duration);
103
    }
104
105
    /**
106
     * Returns the "rough" duration (seconds, minutes, ...) between two Carbon dates.
107
     *
108
     * This function returns a human readable duration such as "5 minutes", "1 month"
109
     * or "45 seconds". To approximate, it's always the biggest quantifier that is used:
110
     * 2 months and 5 days would become "2 months".
111
     *
112
     * @param Carbon  $oldSnapshotTime    The first Carbon date
113
     * @param Carbon  $nextSnapshotTime   The second Carbon date
114
     *
115
     * @return string
116
     */
117
    private function approximateDuration(Carbon $oldSnapshotTime, Carbon $nextSnapshotTime)
118
    {
119
        $years = $oldSnapshotTime->diffInYears($nextSnapshotTime);
120
        if( $years > 0 ) {
121
            return ($years == 1) ? "1 year" : "$years years";
122
        }
123
124
        $months = $oldSnapshotTime->diffInMonths($nextSnapshotTime);
125
        if($months > 0 ) {
126
            return ($months == 1) ? "1 month" : "$months months";
127
        }
128
129
        $days = $oldSnapshotTime->diffInDays($nextSnapshotTime);
130
        if ($days > 0) {
131
            return ($days == 1) ? "1 day" : "$days days";
132
        }
133
134
        $hours = $oldSnapshotTime->diffInHours($nextSnapshotTime);
135
        if ($hours > 0) {
136
            return ($hours == 1) ? "1 hour" : "$hours hours";
137
        }
138
139
        $minutes = $oldSnapshotTime->diffInMinutes($nextSnapshotTime);
140
        if($minutes > 0) {
141
            return ($minutes == 1) ? "1 minute" : "$minutes minutes";
142
        }
143
144
        $seconds = $oldSnapshotTime->diffInSeconds($nextSnapshotTime);
145
        return ($seconds == 1) ? "1 second" : "$seconds seconds";
146
    }
147
148
    public function operationForm()
149
    {
150
        return view('cash.operation');
151
    }
152
153
    public function registerOperation()
154
    {
155
        $amount = floatval(Input::get('amount'));
156
        $currentSnapshotId = $this->snapshotRepository->current()->cs_id;
157
158
        $operationData = ['type' => 'CASH',
159
            'sum' => $amount,
160
            'time' => time(),
161
            'cs_id' => $currentSnapshotId,
162
            'comment' => Input::get('comment')];
163
164
        try {
165
            $this->detailsRepository->store($operationData);
166
        } catch (RepositoryException $e) {
167
            return Redirect::to('app/cash/register-operation')->with('error', 'Could not save operation: ' . $e->getMessage())
168
                ->withInput();
169
        }
170
171
        $message = ($amount < 0) ? 'removed ' . abs($amount) . '&euro; from drawer' : 'added ' . $amount . '&euro; in drawer';
172
        return Redirect::to('app/cash')->with('success', 'Cash operation saved: ' . $message);
173
    }
174
175
    public function snapshotForm()
176
    {
177
        return view('cash.snapshot');
178
    }
179
180
    public function createSnapshot()
181
    {
182
        $title = Input::get('title');
183
184
        try {
185
            $this->snapshotRepository->store(Input::all());
186
        } catch (RepositoryException $e) {
187
            return Redirect::to('app/cash/new-snapshot')->with('error', 'Error while creating snapshot: ' . $e->getMessage())
188
                ->withInput();
189
        }
190
191
        return Redirect::to('app/cash')->with('success', "Cash snapshot <i>$title</i> created");
192
    }
193
194
    public function showHistory()
195
    {
196
        try {
197
            $snapshots = $this->snapshotRepository->history();
198
        } catch (RepositoryException $e) {
199
            App::abort(500);
200
        }
201
202
        return view('cash.history')->with('snapshots', $snapshots);
203
    }
204
205
    public function removeDetail($id)
206
    {
207
        try {
208
209
            DB::beginTransaction();
210
211
            $detailData = $this->detailsRepository->get($id);
212
            $this->detailsRepository->delete($id);
213
            $this->snapshotRepository->updatePredictedAmount($detailData->cs_id);
214
215
            DB::commit();
216
217
        } catch (RepositoryException $e) {
218
            return redirect('app/cash')->with('error', 'An error occurred: ' . strtolower($e->getMessage()));
219
        }
220
221
        return redirect('app/cash')->with('success', "Snapshot item removed");
222
    }
223
224
}
225