ultimatepos/Modules/Maintenance/Resources/views/materials/panel.blade.php

365 lines
20 KiB
PHP

@php
$util = app(\Modules\Maintenance\Utils\MaintenanceUtil::class);
@endphp
<div class="mt-card" id="mm_material_panel" data-source-type="{{ $source_type }}" data-source-id="{{ $source_id }}">
<div class="mt-card-header">
<h3 class="mt-card-title"><i class="fas fa-clipboard-list"></i> @lang('maintenance::lang.material_list')</h3>
</div>
<div class="mt-card-body">
@can('maintenance.materials.manage')
<div class="row" style="margin-bottom:15px;">
<div class="col-md-4">
{!! Form::label('destination_location_id', __('maintenance::lang.mat_destination_location') . ':') !!}
{!! Form::select('destination_location_id',
$locations->pluck('name', 'id'),
$material_list->destination_location_id,
['class' => 'form-control select2 mm_dest_location', 'placeholder' => __('maintenance::lang.select'), 'style' => 'width:100%']) !!}
</div>
<div class="col-md-8 text-left" style="padding-top:24px;">
@if($equipment_id)
<button type="button" class="btn btn-info btn-sm mm_import_bom">
<i class="fa fa-sitemap"></i> @lang('maintenance::lang.mat_import_bom')
</button>
@endif
</div>
</div>
@else
<p class="text-muted">
@lang('maintenance::lang.mat_destination_location'):
{{ $material_list->destinationLocation?->name ?? '—' }}
</p>
@endcan
@can('maintenance.materials.manage')
<div class="well well-sm">
{!! Form::open(['url' => action([\Modules\Maintenance\Http\Controllers\MaterialListController::class, 'storeLine'], [$source_type, $source_id]), 'method' => 'post', 'class' => 'mm_add_line_form']) !!}
<div class="row">
<div class="col-md-4">
{!! Form::select('spare_part_id', $spare_parts, null, ['class' => 'form-control select2', 'placeholder' => __('maintenance::lang.select_spare_part'), 'style' => 'width:100%']) !!}
</div>
<div class="col-md-3">
{!! Form::text('part_name', null, ['class' => 'form-control', 'placeholder' => __('maintenance::lang.mat_or_part_name')]) !!}
</div>
<div class="col-md-2">
{!! Form::select('line_type', ['supply' => __('maintenance::lang.line_type_supply'), 'repair' => __('maintenance::lang.line_type_repair')], 'supply', ['class' => 'form-control']) !!}
</div>
<div class="col-md-2">
{!! Form::number('quantity_required', 1, ['class' => 'form-control', 'min' => '0.001', 'step' => '0.001', 'required']) !!}
</div>
<div class="col-md-1">
<button type="submit" class="btn btn-primary btn-block"><i class="fa fa-plus"></i> @lang('maintenance::lang.add')</button>
</div>
</div>
{!! Form::close() !!}
</div>
@endcan
<ul class="nav nav-tabs" role="tablist">
<li class="active"><a data-toggle="tab" href="#mm_tab_parts">@lang('maintenance::lang.mat_tab_parts')</a></li>
<li><a data-toggle="tab" href="#mm_tab_repair">@lang('maintenance::lang.mat_tab_repair') <span class="badge">{{ ($repair_lines ?? collect())->count() }}</span></a></li>
<li><a data-toggle="tab" href="#mm_tab_purchase">@lang('maintenance::lang.mat_tab_purchase') <span class="badge">{{ count($purchase_shortfall) }}</span></a></li>
</ul>
<div class="tab-content" style="padding-top:15px;">
<div id="mm_tab_parts" class="tab-pane active">
<div class="table-responsive">
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>@lang('maintenance::lang.spare_part')</th>
<th>@lang('maintenance::lang.mat_qty_required')</th>
<th>@lang('maintenance::lang.mat_local_stock')</th>
<th>@lang('maintenance::lang.mat_other_warehouses')</th>
<th>@lang('maintenance::lang.mat_shortfall')</th>
<th>@lang('maintenance::lang.status')</th>
<th>@lang('maintenance::lang.actions')</th>
</tr>
</thead>
<tbody>
@forelse($material_list->lines->where('line_type', 'supply') as $line)
@php $a = $analysis[$line->id] ?? null; @endphp
<tr data-line-id="{{ $line->id }}">
<td>
<strong>{{ $line->displayName() }}</strong>
@if($line->part_number)<br><small class="text-muted">{{ $line->part_number }}</small>@endif
</td>
<td>{{ $a['quantity_required'] ?? $line->quantity_required }}</td>
<td>{{ $a['local_qty'] ?? '—' }}</td>
<td>
@if(!empty($a['other_locations']))
@foreach($a['other_locations'] as $loc)
<div>
<small>
{{ $loc['entity_name'] ? $loc['entity_name'].' / ' : '' }}{{ $loc['location_name'] }}:
<strong>{{ $loc['qty'] }}</strong>
</small>
</div>
@endforeach
@else
<span class="text-muted"></span>
@endif
</td>
<td>
@if(($a['shortfall'] ?? 0) > 0)
<span class="label label-danger">{{ $a['shortfall'] }}</span>
@else
<span class="label label-success">0</span>
@endif
</td>
<td>{{ $status_labels[$line->status] ?? $line->status }}</td>
<td>
@can('maintenance.materials.procure')
@if(!empty($a['other_locations']) && ($a['remaining'] ?? 0) > 0)
<div class="btn-group">
<button type="button" class="btn btn-xs btn-warning mm_transfer_btn dropdown-toggle" data-toggle="dropdown">
@lang('maintenance::lang.mat_request_transfer') <span class="caret"></span>
</button>
<ul class="dropdown-menu">
@foreach($a['other_locations'] as $loc)
<li>
<a href="#" class="mm_do_transfer"
data-line-id="{{ $line->id }}"
data-location-id="{{ $loc['location_id'] }}"
data-max-qty="{{ min($loc['qty'], $a['remaining']) }}">
{{ $loc['location_name'] }} ({{ $loc['qty'] }})
</a>
</li>
@endforeach
</ul>
</div>
@endif
@endcan
@can('maintenance.materials.manage')
@if(!in_array($line->status, ['transfer_in_transit', 'purchase_ordered']))
<button type="button" class="btn btn-xs btn-danger mm_delete_line" data-line-id="{{ $line->id }}">
<i class="fa fa-trash"></i>
</button>
@endif
@endcan
@if($line->procurements->isNotEmpty())
<br><small class="text-muted">
@foreach($line->procurements as $proc)
{{ $proc->procurement_type }}: {{ $proc->transaction?->ref_no ?? '#' }}
@endforeach
</small>
@endif
</td>
</tr>
@empty
<tr><td colspan="7" class="text-center text-muted">@lang('maintenance::lang.no_records')</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div id="mm_tab_repair" class="tab-pane">
@include('maintenance::materials.repair_tab')
</div>
<div id="mm_tab_purchase" class="tab-pane">
@if(empty($purchase_shortfall))
<p class="text-muted">@lang('maintenance::lang.mat_no_purchase_needed')</p>
@else
@can('maintenance.materials.procure')
{!! Form::open(['url' => action([\Modules\Maintenance\Http\Controllers\MaterialListController::class, 'createPurchaseOrders'], [$source_type, $source_id]), 'method' => 'post', 'id' => 'mm_purchase_form']) !!}
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th><input type="checkbox" id="mm_select_all_po" checked></th>
<th>@lang('maintenance::lang.spare_part')</th>
<th>@lang('maintenance::lang.mat_shortfall')</th>
<th>@lang('maintenance::lang.mat_suggested_supplier')</th>
<th>@lang('maintenance::lang.mat_purchase_history')</th>
</tr>
</thead>
<tbody>
@foreach($purchase_shortfall as $idx => $item)
<tr>
<td>
<input type="checkbox" name="lines[{{ $idx }}][selected]" value="1" class="mm_po_line_cb" checked>
<input type="hidden" name="lines[{{ $idx }}][line_id]" value="{{ $item['line_id'] }}">
<input type="hidden" name="lines[{{ $idx }}][quantity]" value="{{ $item['shortfall_qty'] }}">
</td>
<td>{{ $item['display_name'] }}</td>
<td>{{ $item['shortfall_qty'] }}</td>
<td>
<select name="lines[{{ $idx }}][supplier_id]" class="form-control input-sm mm_supplier_select" required style="min-width:180px;">
@if($item['suggested_supplier_id'])
<option value="{{ $item['suggested_supplier_id'] }}" selected>
{{ $item['suggested_supplier_name'] }} (@lang('maintenance::lang.mat_suggested'))
</option>
@endif
@foreach($item['supplier_suggestions'] as $sug)
@if($sug['supplier_id'] != ($item['suggested_supplier_id'] ?? 0))
<option value="{{ $sug['supplier_id'] }}">
{{ $sug['supplier_name'] }} ({{ $sug['purchase_count'] }}x {{ number_format($sug['last_price'], 2) }})
</option>
@endif
@endforeach
</select>
</td>
<td>
@if(!empty($item['supplier_suggestions']))
<ul class="list-unstyled" style="margin:0;font-size:12px;">
@foreach(array_slice($item['supplier_suggestions'], 0, 3) as $sug)
<li>{{ $sug['supplier_name'] }} {{ $sug['last_date'] ? $util->formatDate($sug['last_date']) : '—' }}</li>
@endforeach
</ul>
@else
<span class="text-muted">@lang('maintenance::lang.mat_no_history')</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="text-left">
<button type="submit" class="btn btn-success" name="action" value="po">
<i class="fa fa-shopping-cart"></i> @lang('maintenance::lang.mat_create_po')
</button>
<button type="button" class="btn btn-primary mm_create_requisition_btn">
<i class="fa fa-file-alt"></i> @lang('maintenance::lang.mat_create_requisition')
</button>
</div>
{!! Form::close() !!}
@else
<p class="text-muted">@lang('maintenance::lang.mat_procure_permission_required')</p>
@endcan
@endif
</div>
</div>
</div>
</div>
<script>
$(function() {
var sourceType = $('#mm_material_panel').data('source-type');
var sourceId = $('#mm_material_panel').data('source-id');
$('.mm_dest_location').on('change', function() {
$.post('{{ action([\Modules\Maintenance\Http\Controllers\MaterialListController::class, 'updateDestination'], ['__TYPE__', '__ID__']) }}'
.replace('__TYPE__', sourceType).replace('__ID__', sourceId),
{ destination_location_id: $(this).val(), _token: '{{ csrf_token() }}' },
function(r) { if (r.success !== false) { toastr.success(r.msg || 'OK'); location.reload(); } else { toastr.error(r.msg); } }
);
});
$('.mm_add_line_form').on('submit', function(e) {
e.preventDefault();
var $f = $(this);
$.post($f.attr('action'), $f.serialize(), function(r) {
if (r.success !== false) { toastr.success(r.msg); location.reload(); } else { toastr.error(r.msg); }
});
});
$('.mm_import_bom').on('click', function() {
$.post('{{ action([\Modules\Maintenance\Http\Controllers\MaterialListController::class, 'importBom'], ['__TYPE__', '__ID__']) }}'
.replace('__TYPE__', sourceType).replace('__ID__', sourceId),
{ equipment_id: {{ $equipment_id ?? 'null' }}, _token: '{{ csrf_token() }}' },
function(r) { if (r.success !== false) { toastr.success(r.msg); location.reload(); } else { toastr.error(r.msg); } }
);
});
$('.mm_do_transfer').on('click', function(e) {
e.preventDefault();
var lineId = $(this).data('line-id');
var locId = $(this).data('location-id');
var maxQty = $(this).data('max-qty');
var qty = prompt('{{ __("maintenance::lang.mat_transfer_qty_prompt") }}', maxQty);
if (!qty) return;
$.post('{{ url("maintenance/material-lines") }}/' + lineId + '/transfer', {
source_location_id: locId, quantity: qty, _token: '{{ csrf_token() }}'
}, function(r) {
if (r.success !== false) { toastr.success(r.msg); location.reload(); } else { toastr.error(r.msg); }
});
});
$('.mm_delete_line').on('click', function() {
if (!confirm('{{ __("messages.are_you_sure") }}')) return;
var lineId = $(this).data('line-id');
$.ajax({
url: '{{ url("maintenance/material-lines") }}/' + lineId,
type: 'DELETE',
data: { _token: '{{ csrf_token() }}' },
success: function(r) {
if (r.success !== false) { toastr.success(r.msg); location.reload(); } else { toastr.error(r.msg); }
}
});
});
$('#mm_select_all_po').on('change', function() {
$('.mm_po_line_cb').prop('checked', $(this).is(':checked'));
});
$('#mm_purchase_form').on('submit', function(e) {
$('.mm_po_line_cb').each(function(i) {
if (!$(this).is(':checked')) {
$(this).closest('tr').find('input, select').prop('disabled', true);
}
});
});
$('.mm_create_requisition_btn').on('click', function() {
var lines = [];
$('#mm_purchase_form tbody tr').each(function(i) {
if (!$(this).find('.mm_po_line_cb').is(':checked')) return;
lines.push({
line_id: $(this).find('input[name*="line_id"]').val(),
supplier_id: $(this).find('select[name*="supplier_id"]').val(),
quantity: $(this).find('input[name*="quantity"]').val()
});
});
$.post('{{ action([\Modules\Maintenance\Http\Controllers\MaterialListController::class, 'createPurchaseRequisition'], ['__TYPE__', '__ID__']) }}'
.replace('__TYPE__', sourceType).replace('__ID__', sourceId),
{ lines: lines, _token: '{{ csrf_token() }}' },
function(r) { if (r.success !== false) { toastr.success(r.msg); location.reload(); } else { toastr.error(r.msg); } }
);
});
var mmRepairLineId = null;
$('.mm_open_repair_route').on('click', function() {
mmRepairLineId = $(this).data('line-id');
$('#mm_repair_part_name').text($(this).data('part-name'));
$('#mm_repair_route_modal').modal('show');
});
$('#mm_route_type').on('change', function() {
if ($(this).val() === 'external') {
$('#mm_route_internal_fields').hide();
$('#mm_route_external_fields').show();
} else {
$('#mm_route_internal_fields').show();
$('#mm_route_external_fields').hide();
}
});
$('#mm_holding_entity').on('change', function() {
var entityId = $(this).val();
$('#mm_org_unit').empty().append('<option value="">{{ __("maintenance::lang.select") }}</option>');
if (!entityId) return;
$.get('{{ action([\Modules\Maintenance\Http\Controllers\RepairDispatchController::class, 'orgUnits']) }}', { entity_id: entityId }, function(r) {
if (r.success && r.data) {
$.each(r.data, function(id, name) {
$('#mm_org_unit').append($('<option>', { value: id, text: name }));
});
}
});
});
$('#mm_repair_route_form').on('submit', function(e) {
e.preventDefault();
if (!mmRepairLineId) return;
$.post('{{ url("maintenance/repair-dispatches/line") }}/' + mmRepairLineId, $(this).serialize(), function(r) {
if (r.success !== false) {
toastr.success(r.msg);
location.reload();
} else { toastr.error(r.msg); }
});
});
});
</script>