Fixed reports
This commit is contained in:
miroman-afk
2023-05-02 15:21:54 +03:00
parent 70120653f7
commit fb46c8e739
78 changed files with 21233 additions and 1892 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ vendor/
build.zip
places.xml
*.log
*.log

View File

@@ -1 +0,0 @@
{"status":"success","version":"2.13","file":"http:\/\/portal.hrc.by\/uploads\/modules\/v1\/2.13\/build.zip","name":"v1"}

View File

@@ -4,7 +4,7 @@ namespace App\Commands;
use App\Component\Models\Dishes;
use App\Component\Models\Folders;
use App\Component\Models\OrderBot;
use App\Component\Models\OrderBotStorage;
use App\Component\Models\Settings;
use App\Component\Models\Tasks;
use App\Console\Commands\HRCCommand;
@@ -25,11 +25,11 @@ class GETBot extends HRCCommand implements HRCCommandInterface
Folders::where('is_bot_export', '=', 0)
->update(['is_bot_export' => 1]);
}
$ordersinfo = Tasks::where('method', 'orderinfo')
$orders_info = Tasks::where('method', 'orderinfo')
->get();
$delete_params = ['closed', 'deleted'];
foreach ($ordersinfo as $more) {
$order = OrderBot::where('id', intval($more['more']))
foreach ($orders_info as $more) {
$order = OrderBotStorage::where('id', intval($more['more']))
->whereIn('status', $delete_params)
->get();
foreach ($order as $value) {

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Commands;
use App\Component\Models\Filesystem;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
class GETClearCache extends HRCCommand implements HRCCommandInterface
{
protected $signature = 'getclearcache';
const cacheFolder = CORE_PATH . '/../../Cache/';
public function command($input, $output = null)
{
$code = Filesystem::GetCode($input['token']);
if (isset($input['folder'])) {
Filesystem::ClearFolder(self::cacheFolder . $code . '/' . $input['folder']);
return [
'status' => 'success',
];
}
if (!isset($input['folder'])) {
Filesystem::ClearFolder(self::cacheFolder . $code . '/');
return [
'status' => 'success',
];
}
}
}

View File

@@ -30,6 +30,22 @@ class GETClientInfo extends HRCCommand implements HRCCommandInterface
$orders_sum_current = ShiftOnlineOrders::where('client_code', $client_guid)->where('is_returned', 0)->where('is_deleted', 0)->sum('full_sum');
$orders_count = $orders_count_exchange + $orders_count_current;
$orders_sum = $orders_sum_exchange + $orders_sum_current;
$barcode = Client::getBarcode($client_guid);
if ($client['is_special_price'] == 0) {
$special_price = false;
} else {
$special_price = true;
}
if ($client['is_employee'] == 0) {
$employee = false;
} else {
$employee = true;
}
if ($client['is_block'] == 0) {
$is_block = false;
} else {
$is_block = true;
}
$result = array(
'id' => $client['id'],
'name' => $client['name'],
@@ -41,6 +57,10 @@ class GETClientInfo extends HRCCommand implements HRCCommandInterface
'order_sum' => round($orders_sum, 2),
'presale' => $presale,
'bonus' => intval($bonus),
'barcode' => $barcode,
'special_price' => $special_price,
'employee' => $employee,
'is_block' => $is_block,
)
);
return [

View File

@@ -35,6 +35,7 @@ class GETClientOrders extends HRCCommand implements HRCCommandInterface
return [
'status' => 'success',
'orders' => $orders,
'count' => count($orders)
];
} else {
return [

View File

@@ -3,17 +3,9 @@
namespace App\Commands;
use App\Component\Models\Client;
use App\Component\Models\ClientsAddress;
use App\Component\Models\ClientsBarcode;
use App\Component\Models\ClientsBonus;
use App\Component\Models\ClientsEmail;
use App\Component\Models\ClientsGroup;
use App\Component\Models\ClientsPhone;
use App\Component\Models\ClientsPresale;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class GETClients extends HRCCommand implements HRCCommandInterface
{
@@ -21,99 +13,6 @@ class GETClients extends HRCCommand implements HRCCommandInterface
public function command($input, $output = null)
{
if (isset($input['type']) && $input['type'] == 'loyalty') {
$last_update = Carbon::createFromTimestampUTC($input['last_update'])->timezone('Europe/Minsk');
$phones = ClientsPhone::where('updated_at', '>=', $last_update)->get();
$addresses = ClientsAddress::where('updated_at', '>=', $last_update)->get();
$barcodes = ClientsBarcode::where('updated_at', '>=', $last_update)->get();
$emails = ClientsEmail::where('updated_at', '>=', $last_update)->get();
$presales = ClientsPresale::where('updated_at', '>=', $last_update)->get();
$bonuses = ClientsBonus::where('updated_at', '>=', $last_update)->get();
$clients = Client::where('updated_at', '>=', $last_update)->get();
$info = [];
foreach ($phones as $phone) {
$info[] = $phone['client_guid'];
}
foreach ($addresses as $address) {
$info[] = $address['client_guid'];
}
foreach ($barcodes as $barcode) {
$info[] = $barcode['client_guid'];
}
foreach ($emails as $email) {
$info[] = $email['client_guid'];
}
foreach ($presales as $presale) {
$info[] = $presale['client_guid'];
}
foreach ($bonuses as $bonus) {
$info[] = $bonus['client_guid'];
}
foreach ($clients as $client) {
$info[] = $client['user_code'];
}
$guides = array_values(array_unique($info));
$email = $phone = $client = [];
foreach ($guides as $guid) {
$email_address = Client::getEmail($guid);
$phone_number = Client::getPhone($guid);
$client_info = Client::where('user_code', $guid)->first();
$email[] = array(
'email' => $email_address
);
$phone[] = array(
'phone' => $phone_number
);
$badge[] = array(
'name' => 'Test',
'code' => 1
);
$bonus_dishes[] = array(
'code' => ''
);
if (ClientsBonus::getBonus($guid) > 0) {
$bonus_info[] = array(
'amount' => ClientsBonus::getBonus($guid),
'dishes' => $bonus_dishes
);
} else {
$bonus_info[] = array(
'amount' => ClientsBonus::getBonus($guid)
);
}
$group_info = ClientsGroup::where('code', $client_info['group_id'])->first();
$client[] = array(
'id' => $client_info['id'],
'name' => $client_info['name'],
'guid' => $guid,
'presale' => ClientsPresale::getPresale($guid),
'bonuses' => $bonus_info,
'barcode' => Client::getBarcode($guid),
'group_id' => $client_info['group_id'],
'emails' => $email,
'phones' => $phone,
'badges' => $badge
);
$groups[] = $group_info['code'];
$email = $phone = $badge = $bonus_dishes = $bonus_info = [];
}
$groups_guides = array_values(array_unique($groups));
foreach ($groups_guides as $group) {
$group_info = ClientsGroup::where('code', $group)->first();
$groups_info[] = array(
'id' => $group_info['id'],
'name' => $group_info['name'],
'guid' => $group_info['code'],
);
}
return [
'status' => 'success',
'clients' => $client,
'groups' => $groups_info,
];
}
if (ClientsGroup::where('code', '0')->count() == 0) {
$group = new ClientsGroup([
'code' => '0',
@@ -145,12 +44,33 @@ class GETClients extends HRCCommand implements HRCCommandInterface
$phone = Client::getPhone($client['user_code']);
$email = Client::getEmail($client['user_code']);
$address = Client::getAddress($client['user_code']);
$barcode = Client::getBarcode($client['user_code']);
if ($client['is_special_price'] == 0) {
$special_price = false;
} else {
$special_price = true;
}
if ($client['is_employee'] == 0) {
$employee = false;
} else {
$employee = true;
}
if ($client['is_block'] == 0) {
$is_block = false;
} else {
$is_block = true;
}
$out[] = array(
'id' => $client['id'],
'name' => $client['name'],
'phone' => $phone,
'email' => $email,
'address' => $address,
'barcode' => $barcode,
'special_price' => $special_price,
'employee' => $employee,
'is_block' => $is_block,
);
}
return [

View File

@@ -0,0 +1,95 @@
<?php
namespace App\Commands;
use App\Component\Models\Client;
use App\Component\Models\ClientsAddress;
use App\Component\Models\ClientsBarcode;
use App\Component\Models\ClientsBonus;
use App\Component\Models\ClientsEmail;
use App\Component\Models\ClientsGroup;
use App\Component\Models\ClientsPhone;
use App\Component\Models\ClientsPresale;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class GETCompanyClients extends HRCCommand implements HRCCommandInterface
{
protected $signature = 'getcompanyclients';
public function command($input, $output = null)
{
$dt = Carbon::createFromTimestamp($input['last_update'])->subHours(3);
$last_update = $dt->format('Y-m-d H:i:s');
$clients = Client::select('id', 'name', 'user_code', 'group_id', 'last_change', 'updated_at')
->where('updated_at', '>', $last_update)
->get();
if (count($clients) < 1) {
return [
'status' => 'success',
'clients' => [],
'groups' => [],
];
}
foreach ($clients as $client) {
$email_address = Client::getEmail($client['user_code']);
$phone_number = Client::getPhone($client['user_code']);
$email[] = array(
'email' => $email_address
);
$phone[] = array(
'phone' => $phone_number
);
$badge[] = array(
'name' => 'Test',
'code' => 1
);
$bonus_dishes[] = array(
'code' => ''
);
if (ClientsBonus::getBonus($client['user_code']) > 0) {
$bonus_info[] = array(
'amount' => ClientsBonus::getBonus($client['user_code']),
'dishes' => $bonus_dishes
);
} else {
$bonus_info = array(
'amount' => ClientsBonus::getBonus($client['user_code']),
'dishes' => []
);
}
$group_info = ClientsGroup::where('code', $client['group_id'])->first();
$clients_info[] = array(
'id' => $client['id'],
'name' => $client['name'],
'guid' => $client['user_code'],
'presale' => ClientsPresale::getPresale($client['user_code']),
'bonuses' => $bonus_info,
'barcode' => Client::getBarcode($client['user_code']),
'group_id' => ClientsGroup::getID($client['group_id']),
'emails' => $email,
'phones' => $phone,
'badges' => []
);
$groups[] = $group_info['code'];
$email = $phone = $badge = $bonus_dishes = $bonus_info = [];
}
$groups_guides = array_values(array_unique($groups));
foreach ($groups_guides as $group) {
$group_info = ClientsGroup::where('code', $group)->first();
$groups_info[] = array(
'id' => $group_info['id'],
'name' => $group_info['name'],
'guid' => $group_info['code'],
);
}
return [
'status' => 'success',
'clients' => $clients_info,
'groups' => $groups_info,
];
}
}

256
commands/GETDashboard.php Normal file
View File

@@ -0,0 +1,256 @@
<?php
namespace App\Commands;
use App\Component\Models\Client;
use App\Component\Models\Dishes;
use App\Component\Models\Reasons;
use App\Component\Models\ShiftOnlineActions;
use App\Component\Models\ShiftOnlineDeleted;
use App\Component\Models\ShiftOnlineOrders;
use App\Component\Models\Shifts;
use App\Component\Models\Staff;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Carbon\Carbon;
class GETDashboard extends HRCCommand implements HRCCommandInterface
{
protected $signature = 'getdashboard';
public function command($input, $output = null)
{
if (isset($input['method'])) {
if (isset($input['more'])) {
$more = $input['more'];
} else {
$more = false;
}
if (isset($input['items'])) {
if (isset($input['order_id'])) {
$order_id = $input['order_id'];
} else {
return [
'status' => 'success',
'message' => 'Проверьте введенные данные'
];
}
$items = $input['items'];
} else {
$items = false;
}
if (isset($input['type'])) {
$type = $input['type'];
} else {
$type = false;
}
$method = $input['method'];
} else {
return [
'status' => 'success',
'message' => 'Проверьте введенные данные'
];
}
if ($method == "deleted") {
$count = ShiftOnlineDeleted::count();
if ($count < 1) {
$count = 0;
}
$sum = ShiftOnlineDeleted::selectRaw('SUM(count * sale_price) as sum')->first();
if (isset($sum) && !is_null($sum['sum'])) {
$sum = $sum['sum'];
} else {
$sum = 0;
}
if ($more) {
$deleted_items = ShiftOnlineDeleted::select('order_code')
->selectRaw('SUM(count * sale_price) as sum')
->groupBy('order_code')
->get();
if ($count > 0) {
foreach ($deleted_items as $deleted_item) {
$order = ShiftOnlineOrders::select('opened', 'closed')
->where('code', $deleted_item['order_code'])
->first();
$closed = $order['closed'];
if ($closed == '0000-00-00 00:00:00') {
$closed = '30.12.1899';
}
$orders[] = array(
'number' => $deleted_item['order_code'],
'opened' => $order['opened'],
'closed' => $closed,
'deleted_sum' => round($deleted_item['sum'], 2)
);
}
} else {
$orders = [];
}
return [
'status' => 'success',
'title' => 'Подробнее об удаленных',
'total_sum' => round($sum, 2),
'total_count' => $count,
'deleted_orders' => $orders
];
}
if ($items) {
$all_sum = $all_count = 0;
$deleted_items = ShiftOnlineDeleted::where('order_code', $order_id)
->get();
if ($count > 0) {
foreach ($deleted_items as $deleted_item) {
$order = ShiftOnlineActions::where('order_code', $deleted_item['order_code'])
->where('type_action', 5)
->first();
$out_items[] = array(
'dish' => Dishes::getName($deleted_item['menu_code']),
'time' => $order['time'],
'reason' => Reasons::getName($order['reason']),
'count' => $deleted_item['count'],
'sale_price' => $deleted_item['count'] * $deleted_item['sale_price'],
'who_deleted' => Staff::getName($order['who'])
);
$all_sum += $deleted_item['count'] * $deleted_item['sale_price'];
$all_count += $deleted_item['count'];
}
} else {
$out_items = [];
}
return [
'status' => 'success',
'code' => $order_id,
'all_sum' => round($all_sum, 2),
'all_count' => round($all_count, 3),
'items' => $out_items
];
}
return [
'status' => 'success',
'sum' => round($sum, 2),
'count' => $count
];
}
if ($method == 'guests') {
if ($type == 'median') {
$data = [];
$orders = ShiftOnlineOrders::where('is_waited', 1)
->where('is_deleted', 0)
->get();
if (isset($orders)) {
foreach ($orders as $order) {
$originalTime = $order['opened'];
$newTime = Carbon::createFromFormat('Y-m-d H:i:s', $originalTime)->format('d.m.Y H:i:s');
$data[] = array(
'time' => $newTime,
'count' => $order['client_count']
);
}
}
return [
'status' => 'success',
'data' => $data
];
}
if ($type == 'more') {
$clientsIDS = ShiftOnlineOrders::select('client_code')
->where('is_deleted', 0)
->where('is_returned', 0)
->where('who_open', '<>', 0)
->where('client_code', '<>', '')
->groupBy('client_code')
->get();
$clientsOrdersCount = ShiftOnlineOrders::select('client_code')
->where('is_deleted', 0)
->where('is_returned', 0)
->where('who_open', '<>', 0)
->where('client_code', '<>', '')
->groupBy('client_code')
->count();
if ($clientsOrdersCount > 0) {
foreach ($clientsIDS as $clientsID) {
$orders_info = ShiftOnlineOrders::where('client_code', $clientsID['client_code'])
->where('is_deleted', 0)
->where('is_returned', 0)
->where('who_open', '<>', 0)
->get();
$clientName = Client::getName($clientsID['client_code']);
$clientOrder[$clientName] = [];
foreach ($orders_info as $order_info) {
if ($order_info['closed'] == '0000-00-00 00:00:00') {
$closed = false;
} else {
$closed = $order_info['closed'];
}
$order = array(
'number' => $order_info['code'],
'opened' => $order_info['opened'],
'closed' => $closed,
'sum' => $order_info['order_sum']
);
array_push($clientOrder[$clientName], $order);
}
}
foreach ($clientOrder as $key => $oInfo) {
$out[] = array(
'name' => $key,
'orders' => $oInfo
);
}
return [
'status' => 'success',
'title' => 'Подробнее о заказах гостей',
'clients' => $out
];
} else {
return [
'status' => 'success',
'title' => 'Подробнее о заказах гостей',
'clients' => []
];
}
}
$guests = $namedGuests = $totalSum = 0;
$orders = ShiftOnlineOrders::where('is_waited', 1)
->where('is_deleted', 0)
->get();
if (isset($orders)) {
foreach ($orders as $order) {
$guests += $order['client_count'];
$totalSum += $order['order_sum'];
if ($order['client_code'] != '') {
$namedGuests += 1;
}
}
}
return [
'status' => 'success',
'namedGuests' => $namedGuests,
'guestsCount' => $guests,
'totalSum' => round($totalSum, 2)
];
}
if ($method == 'info') {
$response['status'] = 'success';
$response['exists'] = 'false';
$shifts = Shifts::first();
if (isset($shifts)) {
$response['exists'] = true;
$response['opened'] = $shifts['opened'];
$response['open'] = Staff::getName($shifts['who_open']);
$response['z_number'] = $shifts['z_number'];
if ($shifts['who_close'] > 0) {
$response['closed'] = $shifts['closed'];
$response['close'] = Staff::getName($shifts['who_close']);
}
}
return $response;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
<?php
namespace App\Commands;
use App\Component\Models\User;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
class GETHelloWorld extends HRCCommand implements HRCCommandInterface {
protected $signature = 'gethello';
public function command($input, $output = null) {
$users = User::all();
return [
'status' => 'success',
'users' => $users,
];
}
}

39
commands/GETKeyInfo.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
namespace App\Commands;
use App\Component\Models\Cache;
use App\Console\Commands\HRCEncryptor;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Illuminate\Support\Facades\Log;
class GETKeyInfo extends HRCCommand implements HRCCommandInterface
{
protected $signature = 'getkeyinfo';
public function command($input, $output = null)
{
$cache = Cache::get(245817422, 'v1', $input);
if ($cache) {
return [
'status' => 'success',
'info' => $cache,
'input' => $input
];
}
$info_file = __DIR__ . "\\..\\..\\..\\info.ini";
$key_file = __DIR__ . "\\..\\..\\..\\Key.key";
$unn = parse_ini_file($info_file);
$unn = intval($unn['unn']);
$info = json_decode(HRCEncryptor::decrypt(file_get_contents($key_file), $unn), true);
if (!$cache) {
$cache = Cache::store(245817422, 'v1', $input, $info);
}
return [
'status' => 'success',
'info' => $cache,
'input' => $input
];
}
}

View File

@@ -3,7 +3,7 @@
namespace App\Commands;
use App\Component\Models\ExchangeShifts;
use App\Component\Models\OrderBot;
use App\Component\Models\OrderBotStorage;
use App\Component\Models\Report;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
@@ -19,7 +19,7 @@ class GETOutOrders extends HRCCommand implements HRCCommandInterface {
$out = array('id' => $shift['id'], 'opened' => $shift['opened'], 'closed' => $shift['closed']);
}
}
$orders = OrderBot::select('id', 'order', 'created_at')->where('created_at', '>', $out['opened'])->where('created_at', '<=', $out['closed'])->get();
$orders = OrderBotStorage::select('id', 'order', 'created_at')->where('created_at', '>', $out['opened'])->where('created_at', '<=', $out['closed'])->get();
$count_items = 0;
if (is_array($orders) || is_object($orders)) {
foreach ($orders as $order) {
@@ -73,7 +73,7 @@ class GETOutOrders extends HRCCommand implements HRCCommandInterface {
$end_t = strtotime($input['end_date']) - 1;
$start = date('Y-m-d H:i:s', $start_t);
$end = date('Y-m-d H:i:s', $end_t);
$orders = OrderBot::select('id', 'order', 'created_at')->where('created_at', '>', $start)->where('created_at', '<=', $end)->get();
$orders = OrderBotStorage::select('id', 'order', 'created_at')->where('created_at', '>', $start)->where('created_at', '<=', $end)->get();
$count_items = 0;
if (is_array($orders) || is_object($orders)) {
foreach ($orders as $order) {

View File

@@ -10,7 +10,7 @@ class GETReports extends HRCCommand implements HRCCommandInterface {
protected $signature = 'getreports';
public function command($input, $output = null) {
$reports = Report::all();
$reports = Report::select('id', 'name', 'report_type', 'start_date', 'end_date')->orderBy('id', 'desc')->get();
if ($reports) {
foreach ($reports as $key => $report) {
$data[] = array(

View File

@@ -3,6 +3,8 @@
namespace App\Commands;
use App\Component\Models\Settings;
use App\Component\Commands\Methods\Cache;
use App\Component\Models\Terminal;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
@@ -12,6 +14,34 @@ class GETSettings extends HRCCommand implements HRCCommandInterface
public function command($input, $output = null)
{
if (isset($input['method'])) {
$method = $input['method'];
if ($method == 'terminals') {
$out = [];
$terminals = Terminal::get();
foreach ($terminals as $terminal) {
if ($terminal['is_active'] === 1) {
$is_active = true;
} else {
$is_active = false;
}
$out[] = array(
'work_code' => $terminal['work_code'],
'work_group' => $terminal['work_group'],
'soft' => $terminal['soft'],
'is_active' => $is_active,
'key' => $terminal['key'],
'last_activity' => $terminal['last_activity'],
);
}
return [
'status' => 'success',
'terminals' => $out,
];
}
}
if (isset($input['code'])) {
$setting = Settings::where('code', $input['code'])
->first();

View File

@@ -3,7 +3,8 @@
namespace App\Commands;
use App\Component\Models\Dishes;
use App\Component\Models\OnlineItems;
use App\Component\Models\ShiftOnlineItems;
use App\Component\Models\ShiftOnlineOrders;
use App\Component\Models\Terminal;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
@@ -18,8 +19,21 @@ class GETTopDishes extends HRCCommand implements HRCCommandInterface {
} else {
$terminalKey = 0;
}
$info = OnlineItems::where('menu_code', '>', 0)->get()->unique('menu_code');
$count = OnlineItems::where('menu_code', '>', 0)->count();
$allOrders = ShiftOnlineOrders::select('code')
->where('is_closed', 1)
->where('is_returned', 0)
->where('is_deleted', 0)
->get();
foreach ($allOrders as $order) {
$orders[] = array($order['code']);
}
$info = ShiftOnlineItems::where('menu_code', '>', 0)
->whereIn('order_code', $orders)
->get()
->unique('menu_code');
$count = ShiftOnlineItems::where('menu_code', '>', 0)
->whereIn('order_code', $orders)
->count();
if ($count > 0) {
foreach ($info as $key => $value) {
$out[] = $value;
@@ -29,18 +43,22 @@ class GETTopDishes extends HRCCommand implements HRCCommandInterface {
->where('legacy_code', '=', $item['dish_code'])
->where('is_history', '=', 0)
->first();
$onlineDishInfo = OnlineItems::where('menu_code', '=', $item['menu_code'])
$onlineDishInfo = ShiftOnlineItems::where('menu_code', '=', $item['menu_code'])
->where('dish_code', '=', $item['dish_code'])
->whereIn('order_code', $orders)
->first();
if ($dishInfo['name'] == '') {
$dishHistInfo = Dishes::where('code', '=', $item['menu_code'])
->where('legacy_code', '=', $item['dish_code'])
->whereIn('order_code', $orders)
->first();
$dishName = $dishHistInfo['name'];
} else {
$dishName = $dishInfo['name'];
}
$dishCount = OnlineItems::where('menu_code', '=', $item['menu_code'])->sum('count');
$dishCount = ShiftOnlineItems::where('menu_code', '=', $item['menu_code'])
->whereIn('order_code', $orders)
->sum('count');
$dishSum = $onlineDishInfo['real_price'] * $dishCount;
if ($dishSum > 0) {
$dishTotalCost = round(($onlineDishInfo['special_price'] * $dishCount), 2);

View File

@@ -2,9 +2,11 @@
namespace App\Commands;
use App\Component\Models\Client;
use App\Component\Models\ClientsBonus;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class POSTBonus extends HRCCommand implements HRCCommandInterface
@@ -13,13 +15,17 @@ class POSTBonus extends HRCCommand implements HRCCommandInterface
public function command($input, $output = null)
{
$client_guid = $input['client_id'];
$client_guid = $input['client_guid'];
$bonus_amount = abs($input['amount']);
$staff_id = $input['who'];
$staff_id = $input['who_id'];
$bonus_time = $input['date_transaction'];
$type = $input['type'];
ClientsBonus::bonusReg($client_guid, $bonus_amount, $type);
ClientsBonus::bonusLog($client_guid, $bonus_amount, $bonus_time, $staff_id);
$client = Client::where('user_code', $client_guid)->first();
$client = Client::find($client['id']);
$client->updated_at = Carbon::createFromTimestampUTC($bonus_time)->timezone('Europe/Minsk');
$client->save();
if ($type == 'in') {
$message = 'Начислено ' . $bonus_amount . ' бонусов';
} elseif ($type == 'out') {

View File

@@ -12,119 +12,295 @@ use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Illuminate\Support\Facades\Log;
class POSTClient extends HRCCommand implements HRCCommandInterface {
protected $signature = 'postclient';
class POSTClient extends HRCCommand implements HRCCommandInterface
{
protected $signature = 'postclient';
public function command($input, $output = null) {
public function command($input, $output = null)
{
if (isset($input['task']) && isset($input['id'])) {
if ($input['task'] == 'update') {
$phone = urldecode($input['phone']);
$client = Client::find($input['id']);
$client->name = urldecode($input['name']);
$client->unloaded = 0;
$clientGroup = ClientsGroup::where('id', $input['group_id'])->first();
$client->group_id = urldecode($clientGroup['code']);
$clientPhone = ClientsPhone::where('client_guid', $client->user_code)->first();
if ($clientPhone) {
$clientPhone = ClientsPhone::find($clientPhone['id']);
if ($phone !== '' && $phone !== '+375 ( ) - -') {
if (substr($phone, 0, 1) == '+') {
$phoneData = urldecode($input['phone']);
} else {
$phoneData = urldecode($input['phone']);
$clientPhone->phone = '+375 (' . substr($phoneData, 0, 2) . ') ' . substr($phoneData, 2, 3) . '-' . substr($phoneData, 5, 2) . '-' . substr($phoneData, 7, 2);
}
} else {
$clientPhone->phone = '+375 ( ) - -';
}
$clientPhone->save();
}
if (isset($input['task'])) {
if ($input['task'] == 'update') {
log::debug($input);
if (isset($input['id'])) {
$id = $input['id'];
} else if (isset($input['client_guid'])) {
$fClient = Client::where('user_code', $input['client_guid'])->first();
if (!isset($fClient)) {
return [
'status' => 'success',
'error_message' => 'Клиент не найден',
];
}
$id = $fClient['id'];
} else {
return [
'status' => 'success',
'error_message' => 'Проверьте введенные данные',
];
}
if (isset($input['group_id']) && !isset($input['group_guid'])) {
$group_id = $input['group_id'];
} else if (isset($input['group_guid']) && !isset($input['group_id'])) {
$fGroup = ClientsGroup::where('code', $input['group_guid'])->first();
if (!isset($fGroup)) {
return [
'status' => 'success',
'error_message' => 'Группа не найдена',
];
}
$group_id = $fGroup['id'];
} else if (isset($input['group_id']) && isset($input['group_guid'])) {
$fGroup = ClientsGroup::where('code', $input['group_guid'])->first();
if (!isset($fGroup)) {
$fGroup = ClientsGroup::where('id', isset($input['group_id']))->first();
if (!isset($fGroup)) {
return [
'status' => 'success',
'error_message' => 'Группа не найдена',
];
}
}
$group_id = $fGroup['id'];
} else {
return [
'status' => 'success',
'error_message' => 'Проверьте введенные данные',
];
}
$client = Client::find($id);
$client->name = urldecode($input['name']);
$client->unloaded = 0;
$clientGroup = ClientsGroup::where('id', $group_id)->first();
$client->group_id = $clientGroup['code'];
$clientEmail = ClientsEmail::where('client_guid', $client->user_code)->first();
if ($clientEmail) {
$clientEmail = ClientsEmail::find($clientEmail['id']);
if ($input['email'] !== '') {
$clientEmail->email = urldecode($input['email']);
} else {
$clientEmail->email = '';
}
$clientEmail->save();
}
if (isset($input['phone'])) {
$phone = $input['phone'];
Log::debug($phone);
$clientPhone = ClientsPhone::where('client_guid', $client->user_code)->first();
Log::debug($clientPhone);
if (isset($clientPhone)) {
$clientPhone = ClientsPhone::find($clientPhone['id']);
if ($phone !== '' && $phone !== '+375 ( ) - -') {
if (substr($phone, 0, 1) == '+') {
$clientPhone->phone = '+375 (' . substr($phone, 4, 2) . ') ' . substr($phone, 6, 3) . '-' . substr($phone, 9, 2) . '-' . substr($phone, 11, 2);
log::debug('UPD Substr true: ' . $phone);
} else {
log::debug('UPD Substr false: ' . $phone);
$clientPhone->phone = '+375 (' . substr($phone, 0, 2) . ') ' . substr($phone, 2, 3) . '-' . substr($phone, 5, 2) . '-' . substr($phone, 7, 2);
}
} else {
$clientPhone->phone = '+375 ( ) - -';
}
} else {
$clientPhone = new ClientsPhone;
if ($phone !== '' && $phone !== '+375 ( ) - -') {
if (substr($phone, 0, 1) == '+') {
$clientPhone->phone = '+375 (' . substr($phone, 4, 2) . ') ' . substr($phone, 6, 3) . '-' . substr($phone, 9, 2) . '-' . substr($phone, 11, 2);
log::debug('CR Substr true: ' . $phone);
} else {
log::debug('CR Substr false: ' . $phone);
$clientPhone->phone = '+375 (' . substr($phone, 0, 2) . ') ' . substr($phone, 2, 3) . '-' . substr($phone, 5, 2) . '-' . substr($phone, 7, 2);
}
} else {
$clientPhone->phone = '+375 ( ) - -';
}
}
$clientPhone->client_guid = $client->user_code;
$clientPhone->save();
}
$clientAddress = ClientsAddress::where('client_guid', $client->user_code)->first();
if ($clientAddress) {
$clientAddress = ClientsAddress::find($clientAddress['id']);
if ($input['address'] !== '') {
$clientAddress->address = urldecode($input['address']);
} else {
$clientAddress->address = '';
}
$clientAddress->save();
}
if (isset($input['email'])) {
$clientEmail = ClientsEmail::where('client_guid', $client->user_code)->first();
if ($clientEmail) {
$clientEmail = ClientsEmail::find($clientEmail['id']);
if (isset($input['email']) && $input['email'] !== '') {
$clientEmail->email = urldecode($input['email']);
} else {
$clientEmail->email = '';
}
} else {
$clientEmail = new ClientsEmail;
$clientEmail->email = urldecode($input['email']);
}
$clientEmail->client_guid = $client->user_code;
$clientEmail->save();
} else {
$clientEmail = '';
}
$clientBarcode = ClientsBarcode::where('client_guid', $client->user_code)->first();
if ($clientBarcode) {
$clientBarcode = ClientsBarcode::find($clientBarcode['id']);
if ($input['barcode'] !== '') {
$clientBarcode->code_id = urldecode($input['barcode']);
} else {
$clientBarcode->code_id = '';
}
$clientBarcode->save();
}
if (isset($input['address'])) {
$clientAddress = ClientsAddress::where('client_guid', $client->user_code)->first();
if ($clientAddress) {
$clientAddress = ClientsAddress::find($clientAddress['id']);
if ($input['address'] !== '') {
$clientAddress->address = urldecode($input['address']);
} else {
$clientAddress->address = '';
}
} else {
$clientAddress = new ClientsAddress;
$clientAddress->address = urldecode($input['address']);
}
$clientAddress->client_guid = $client->user_code;
$clientAddress->save();
}
$clientBarcodeStart = 0;
$clientBarcodeEnd = 0;
if (isset($input['barcode'])) {
if ($input['barcode'] !== '') {
$client->barcode_type = 2;
$client->barcode_start = $clientBarcodeStart = urldecode($input['barcode']);
$client->barcode_end = $clientBarcodeEnd = urldecode($input['barcode']);
} else {
$client->barcode_type = 1;
$client->barcode_start = $clientBarcodeStart;
$client->barcode_end = $clientBarcodeEnd;
}
}
if (isset($input['is_special_price']) && $input['is_special_price'] == 'true') {
$specialPrice = 1;
} else {
$specialPrice = 0;
}
if (isset($input['is_employee']) && $input['is_employee'] == 'true') {
$employee = 1;
} else {
$employee = 0;
}
$client->is_special_price = $specialPrice;
$client->is_employee = $employee;
$client->save();
return [
'status' => 'success',
'client' => $client,
'phone' => $clientPhone,
'email' => $clientEmail,
'address' => $clientAddress,
'barcode' => $clientBarcode,
'message' => 'Клиент обновлен',
];
}
return [
'status' => 'success',
'client' => $client,
'phone' => $clientPhone,
'email' => $clientEmail,
'address' => $clientAddress,
'barcode' => $clientBarcodeStart,
'message' => 'Клиент обновлен',
];
}
if ($input['task'] == 'delete') {
$client = Client::find($input['id']);
$clientGroup = ClientsGroup::where('code', $client->group_id)->first();
$clientPhone = ClientsPhone::where('client_guid', $client->user_code)->first();
$clientPhone = ClientsPhone::find($clientPhone['id']);
$clientEmail = ClientsEmail::where('client_guid', $client->user_code)->first();
$clientEmail = ClientsEmail::find($clientEmail['id']);
$clientAddress = ClientsAddress::where('client_guid', $client->user_code)->first();
$clientAddress = ClientsAddress::find($clientAddress['id']);
$clientBarcode = ClientsBarcode::where('client_guid', $client->user_code)->first();
$clientBarcode = ClientsBarcode::find($clientBarcode['id']);
if ($clientPhone) {
$clientPhone->delete();
}
if ($clientEmail) {
$clientEmail->delete();
}
if ($clientAddress) {
$clientAddress->delete();
}
if ($clientBarcode) {
$clientBarcode->delete();
}
if ($client) {
$client->delete();
}
if ($input['task'] == 'delete') {
$client = Client::find($input['id']);
$clientGroup = ClientsGroup::where('code', $client->group_id)->first();
$clientPhone = ClientsPhone::where('client_guid', $client->user_code)->first();
$clientPhone = ClientsPhone::find($clientPhone['id']);
$clientEmail = ClientsEmail::where('client_guid', $client->user_code)->first();
$clientEmail = ClientsEmail::find($clientEmail['id']);
$clientAddress = ClientsAddress::where('client_guid', $client->user_code)->first();
$clientAddress = ClientsAddress::find($clientAddress['id']);
$clientBarcode = ClientsBarcode::where('client_guid', $client->user_code)->first();
$clientBarcode = ClientsBarcode::find($clientBarcode['id']);
if ($clientPhone) {
$clientPhone->delete();
}
if ($clientEmail) {
$clientEmail->delete();
}
if ($clientAddress) {
$clientAddress->delete();
}
if ($clientBarcode) {
$clientBarcode->delete();
}
if ($client) {
$client->delete();
}
return [
'status' => 'success',
'message' => 'Клиент удален',
'currentGroup' => $clientGroup['id'],
];
}
} else {
return [
'status' => 'success',
'error_message' => 'Проверьте введенные данные',
];
}
}
return [
'status' => 'success',
'message' => 'Клиент удален',
'currentGroup' => $clientGroup['id'],
];
}
if ($input['task'] == 'lock') {
if (isset($input['id'])) {
$id = $input['id'];
} else if (isset($input['client_guid'])) {
$fClient = Client::where('user_code', $input['client_guid'])->first();
if (!isset($fClient)) {
return [
'status' => 'success',
'error_message' => 'Клиент не найден',
];
}
$id = $fClient['id'];
} else {
return [
'status' => 'success',
'error_message' => 'Проверьте введенные данные',
];
}
$client = Client::find($id);
$clientGroup = ClientsGroup::where('code', $client->group_id)->first();
$client->is_block = 1;
$client->save();
return [
'status' => 'success',
'message' => 'Клиент заблокирован',
'currentGroup' => $clientGroup['id'],
];
}
if ($input['task'] == 'unlock') {
if (isset($input['id'])) {
$id = $input['id'];
} else if (isset($input['client_guid'])) {
$fClient = Client::where('user_code', $input['client_guid'])->first();
if (!isset($fClient)) {
return [
'status' => 'success',
'error_message' => 'Клиент не найден',
];
}
$id = $fClient['id'];
} else {
return [
'status' => 'success',
'error_message' => 'Проверьте введенные данные',
];
}
$client = Client::find($id);
$clientGroup = ClientsGroup::where('code', $client->group_id)->first();
$client->is_block = 0;
$client->save();
return [
'status' => 'success',
'message' => 'Клиент разблокирован',
'currentGroup' => $clientGroup['id'],
];
}
if ($input['task'] == 'search' && isset($input['name'])) {
$client = Client::where('name', 'like', '%' . urldecode($input['name']) . '%')->get();
if (count($client) > 0) {
$message = 'Клиенты найдены!';
} else {
$message = 'Клиенты с именем ' . urldecode($input['name']) . ' не найдены!';
}
return [
'status' => 'success',
'message' => $message,
'clients' => $client
];
}
} else {
return [
'status' => 'success',
'error_message' => 'Проверьте введенные данные',
];
}
}
}

View File

@@ -30,11 +30,26 @@ class POSTCreateClient extends HRCCommand implements HRCCommandInterface {
}
$total = Client::where('name', '=', $input['name'])->count();
if (isset($input['client_guid'])) {
$check_guid = Client::where('user_code', $input['client_guid'])->count();
if ($check_guid > 0) {
return [
'status' => 'success',
'message' => 'Клиент уже существует'
];
}
}
$client_code = Client::max('code') + 1;
if (isset($input['is_special_price']) && $input['is_special_price'] == 'true') {
$specialPrice = 1;
} else {
$specialPrice = 0;
}
if (isset($input['is_employee']) && $input['is_employee'] == 'true') {
$employee = 1;
} else {
$employee = 0;
}
$client = new Client;
if ($total >= 1) {
$total = $total + 1;
@@ -42,10 +57,17 @@ class POSTCreateClient extends HRCCommand implements HRCCommandInterface {
} else {
$client->name = urldecode($input['name']);
}
$client->user_code = strtoupper(md5(time()));
if (!isset($input['client_guid'])) {
$client->user_code = strtoupper(md5(time()));
} else {
$client->user_code = $input['client_guid'];
}
$client->code = $client_code;
$client->group_id = $group['code'];
$client->is_special_price = $specialPrice;
$client->is_employee = $employee;
$client->last_change = date("Ymd");
$clientEmail = new ClientsEmail;
$clientEmail->email = urldecode($input['email']);
$clientEmail->client_guid = $client->user_code;
@@ -55,7 +77,7 @@ class POSTCreateClient extends HRCCommand implements HRCCommandInterface {
$clientAddress->client_guid = $client->user_code;
$clientPhone = new ClientsPhone;
if ($input['phone'] !== '') {
if ($input['phone'] !== '' && isset($input['phone'])) {
$phoneData = urldecode($input['phone']);
$phone = '+375 (' . substr($phoneData, 0, 2) . ') ' . substr($phoneData, 2, 3) . '-' . substr($phoneData, 5, 2) . '-' . substr($phoneData, 7, 2);
} else {
@@ -65,7 +87,7 @@ class POSTCreateClient extends HRCCommand implements HRCCommandInterface {
$clientPhone->client_guid = $client->user_code;
if (isset($input['barcode']) && $input['barcode'] > 0) {
$client->barcode_type = 1;
$client->barcode_type = 2;
$clientBarcode = new ClientsBarcode;
$clientBarcode->code_id = urldecode($input['barcode']);
$clientBarcode->name = '';
@@ -73,13 +95,15 @@ class POSTCreateClient extends HRCCommand implements HRCCommandInterface {
$clientBarcode->value = urldecode($input['barcode']);
$clientBarcode->block = 0;
$clientBarcode->symptom_block = 0;
$client->barcode_start = urldecode($input['barcode']);
$client->barcode_end = urldecode($input['barcode']);
$client->save();
$clientPhone->save();
$clientEmail->save();
$clientAddress->save();
$clientBarcode->save();
} else {
$client->barcode_type = 0;
$client->barcode_type = 1;
$client->save();
$clientPhone->save();
$clientEmail->save();

View File

@@ -2,11 +2,16 @@
namespace App\Commands;
use App\Component\Models\Base;
use App\Component\Models\Dishes;
use App\Component\Models\OrderBot;
use App\Component\Models\OrderBotStorage;
use App\Component\Models\OrderItems;
use App\Component\Models\Orders;
use App\Component\Models\TerminalUpdate;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Carbon\Carbon;
class POSTOrder extends HRCCommand implements HRCCommandInterface {
protected $signature = 'postorder';
@@ -97,6 +102,132 @@ class POSTOrder extends HRCCommand implements HRCCommandInterface {
];
}
if ($input['task'] == 'pay' && isset($input['info'])) {
$test_json = Base::validate_json(urldecode($input['info']));
if (!$test_json) {
return [
'status' => 'fail',
'message' => 'Ошибка обработки JSON',
];
}
$order_info = json_decode(urldecode($input['info']), true);
if (isset($order_info['order_id'])) {
$order_id = intval($order_info['order_id']);
$order = OrderBotStorage::where('id', $order_id)->first();
if (!isset($order)) {
return [
'status' => 'fail',
'message' => 'Заказ с данным ID не найден',
];
}
} else {
return [
'status' => 'fail',
'message' => 'Отсутствует ID заказа',
];
}
if (isset($order_info['transaction_id'])) {
$transaction_id = intval($order_info['transaction_id']);
$order_data = json_decode(base64_decode($order['order']), true);
if ($transaction_id != $order_data['id']) {
return [
'status' => 'fail',
'message' => 'ID заказа не соответствует ID транзакции',
];
}
} else {
return [
'status' => 'fail',
'message' => 'Отсутствует ID транзакции',
];
}
if (isset($order_info['time'])) {
$pay_time = $order_info['time'];
if ($pay_time < $order['created_at']) {
return [
'status' => 'fail',
'message' => 'Время создания заказа больше чем время оплаты',
];
}
} else {
return [
'status' => 'fail',
'message' => 'Отсутствует время оплаты заказа',
];
}
if (isset($order_info['amount'])) {
$amount = floatval($order_info['amount']);
if ($amount != floatval($order_data['price'])) {
return [
'status' => 'fail',
'message' => 'Сумма оплаты не соответствует сумме заказа',
];
}
} else {
return [
'status' => 'fail',
'message' => 'Отсутствует сумма оплаты',
];
}
if (isset($order_info['is_print'])) {
$is_print = $order_info['is_print'];
} else {
$is_print = false;
}
if (isset($order_info['is_closed'])) {
$is_closed = $order_info['is_closed'];
} else {
$is_closed = false;
}
if ($order['is_send'] === 0) {
return [
'status' => 'fail',
'message' => 'Заказ ещё не отправлен',
];
} else {
$pay_task = array(
'order_id' => $order_id,
'transaction_id' => $transaction_id,
'time' => $pay_time,
'amount' => $amount,
'is_print' => $is_print,
'is_closed' => $is_closed
);
$todayDate = Carbon::now('Europe/Minsk')->format('Y-m-d H:i:m');
$bot_info = OrderBot::first();
$terminal_id = $bot_info['terminal_id'];
$check_order = TerminalUpdate::where('method', 'payorder')
->where('more', base64_encode(json_encode($pay_task)))
->count();
if ($check_order > 0) {
return [
'status' => 'fail',
'message' => 'Задача оплаты в обработке',
];
}
$task = new TerminalUpdate;
$task->terminal_id = $terminal_id;
$task->next_at = $todayDate;
$task->method = 'payorder';
$task->period = 1;
$task->is_cycle = 0;
$task->more = base64_encode(json_encode($pay_task));
$task->save();
}
return [
'status' => 'success',
'message' => 'Информация об оплате отправлена',
];
}
} else {
return [
'status' => 'success',

View File

@@ -2,9 +2,11 @@
namespace App\Commands;
use App\Component\Models\Client;
use App\Component\Models\ClientsPresale;
use App\Console\Commands\HRCCommand;
use App\Console\Commands\HRCCommandInterface;
use Carbon\Carbon;
class POSTPresale extends HRCCommand implements HRCCommandInterface
{
@@ -12,18 +14,19 @@ class POSTPresale extends HRCCommand implements HRCCommandInterface
public function command($input, $output = null)
{
$client_guid = $input['client_id'];
$client_guid = $input['client_guid'];
$presale_amount = abs($input['amount']);
$staff_id = $input['who'];
$staff_id = $input['who_id'];
$presale_time = $input['date_transaction'];
$type = $input['type'];
$action_type = intval($input['action_type']);
$code_order = intval($input['code_order']);
ClientsPresale::presaleReg($client_guid, $presale_amount, $type);
ClientsPresale::presaleLog($client_guid, $presale_amount, $presale_time, $staff_id);
if ($type == 'in') {
$message = 'Внесен аванс на сумму ' . $presale_amount . ' BYN';
} elseif ($type == 'out') {
$message = 'Зачтен аванс на сумму ' . $presale_amount . ' BYN';
}
$message = ClientsPresale::presaleLog($client_guid, $presale_amount, $presale_time, $staff_id, $action_type, $code_order);
$client = Client::where('user_code', $client_guid)->first();
$client = Client::find($client['id']);
$client->updated_at = Carbon::createFromTimestampUTC($presale_time)->timezone('Europe/Minsk');
$client->save();
$presale_result = ClientsPresale::getPresale($client_guid);
return [
'status' => 'success',

View File

@@ -1,10 +1,12 @@
{
"name": "hrc-admin/hello-world",
"version": "2.26",
"version": "2.27",
"require": {
"horeca/admin-php-module-core": "dev-master",
"guzzlehttp/guzzle": "^7.4",
"phpmailer/phpmailer": "^6.6"
"phpmailer/phpmailer": "^6.6",
"ext-openssl": "*",
"ext-json": "*"
},
"repositories": [
{

7
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c03123a7ef4b356dbbe431d73497088d",
"content-hash": "a8af6b76ceb6599b09c480a9985c90b3",
"packages": [
{
"name": "brick/math",
@@ -5896,7 +5896,10 @@
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform": {
"ext-openssl": "*",
"ext-json": "*"
},
"platform-dev": [],
"plugin-api-version": "2.0.0"
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddOrderIdColumnInClientsActions extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up() {
if (!Schema::hasColumn('clients_actions', 'order_id')) {
Schema::table('clients_actions', function (Blueprint $table) {
$table->integer('order_id')->nullable();
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down() {
Schema::table('clients_actions', function (Blueprint $table) {
$table->dropColumn('order_id');
});
}
}

View File

@@ -0,0 +1,70 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateCoreInterface227 extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$directivesUpd = CORE_PATH . '/../V1/forUpdate/toDirectives/';
$indexUpd = CORE_PATH . '/../V1/forUpdate/toWebApp/';
$servicesUpd = CORE_PATH . '/../V1/forUpdate/toServices/';
$libsUpd = CORE_PATH . '/../V1/forUpdate/toLibs/datatables/';
if (is_dir($directivesUpd)) {
$files = array_diff(scandir($directivesUpd), array('.', '..'));
foreach ($files as $file) {
if (file_exists(CORE_PATH . '/../../web/app/scripts/directives/' . $file)) {
copy(CORE_PATH . '/../../web/app/scripts/directives/' . $file, CORE_PATH . '/../../web/app/scripts/directives/' . $file . '.bak');
}
copy($directivesUpd . $file, CORE_PATH . '/../../web/app/scripts/directives/' . $file);
}
}
if (is_dir($indexUpd)) {
$files = array_diff(scandir($indexUpd), array('.', '..'));
foreach ($files as $file) {
if (file_exists(CORE_PATH . '/../../web/app/' . $file)) {
copy(CORE_PATH . '/../../web/app/' . $file, CORE_PATH . '/../../web/app/' . $file . '.bak');
}
copy($indexUpd . $file, CORE_PATH . '/../../web/app/' . $file);
}
}
if (is_dir($servicesUpd)) {
$files = array_diff(scandir($servicesUpd), array('.', '..'));
foreach ($files as $file) {
if (file_exists(CORE_PATH . '/../../web/app/scripts/services/' . $file)) {
copy(CORE_PATH . '/../../web/app/scripts/services/' . $file, CORE_PATH . '/../../web/app/scripts/services/' . $file . '.bak');
}
copy($servicesUpd . $file, CORE_PATH . '/../../web/app/scripts/services/' . $file);
}
}
if (is_dir($libsUpd)) {
$files = array_diff(scandir($libsUpd), array('.', '..'));
if (!is_dir(CORE_PATH . '/../../web/libs/datatables/')) {
mkdir(CORE_PATH . '/../../web/libs/datatables/', 0777);
}
foreach ($files as $file) {
if (file_exists(CORE_PATH . '/../../web/libs/datatables/' . $file)) {
copy(CORE_PATH . '/../../web/libs/datatables/' . $file, CORE_PATH . '/../../web/libs/datatables//' . $file . '.bak');
}
copy($libsUpd . $file, CORE_PATH . '/../../web/libs/datatables/' . $file);
}
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
}

View File

@@ -0,0 +1,29 @@
<?php
use App\Component\Models\Filesystem;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Log;
class DeleteFrontendFolders227 extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up() {
if (file_exists(CORE_PATH . '/../Staff/web/')) {
Filesystem::ClearFolder((CORE_PATH . '/../Staff/web/'));
} else {
Log::debug('Staff frontend already deleted!');
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down() {
//
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
/*!
* Print button for Buttons and DataTables.
* 2016 SpryMedia Ltd - datatables.net/license
*/
!function(n){"function"==typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(t){return n(t,window,document)}):"object"==typeof exports?module.exports=function(t,e){return t=t||window,(e=e||("undefined"!=typeof window?require("jquery"):require("jquery")(t))).fn.dataTable||require("datatables.net")(t,e),e.fn.dataTable.Buttons||require("datatables.net-buttons")(t,e),n(e,t,t.document)}:n(jQuery,window,document)}(function(m,b,t,p){"use strict";function h(t){return n.href=t,-1===(t=n.host).indexOf("/")&&0!==n.pathname.indexOf("/")&&(t+="/"),n.protocol+"//"+t+n.pathname+n.search}var e=m.fn.dataTable,n=t.createElement("a");return e.ext.buttons.print={className:"buttons-print",text:function(t){return t.i18n("buttons.print","Print")},action:function(t,e,n,o){function r(t,e){for(var n="<tr>",o=0,r=t.length;o<r;o++){var i=null===t[o]||t[o]===p?"":t[o];n+="<"+e+" "+(s[o]?'class="'+s[o]+'"':"")+">"+i+"</"+e+">"}return n+"</tr>"}var i=e.buttons.exportData(m.extend({decodeEntities:!1},o.exportOptions)),a=e.buttons.exportInfo(o),s=e.columns(o.exportOptions.columns).flatten().map(function(t){return e.settings()[0].aoColumns[e.column(t).index()].sClass}).toArray(),u='<table class="'+e.table().node().className+'">';o.header&&(u+="<thead>"+r(i.header,"th")+"</thead>"),u+="<tbody>";for(var d=0,c=i.body.length;d<c;d++)u+=r(i.body[d],"td");u+="</tbody>",o.footer&&i.footer&&(u+="<tfoot>"+r(i.footer,"th")+"</tfoot>"),u+="</table>";var l=b.open("","");if(l){l.document.close();var f="<title>"+a.title+"</title>";m("style, link").each(function(){f+=function(t){t=m(t).clone()[0];return"link"===t.nodeName.toLowerCase()&&(t.href=h(t.href)),t.outerHTML}(this)});try{l.document.head.innerHTML=f}catch(t){m(l.document.head).html(f)}l.document.body.innerHTML="<h1>"+a.title+"</h1><div>"+(a.messageTop||"")+"</div>"+u+"<div>"+(a.messageBottom||"")+"</div>",m(l.document.body).addClass("dt-print-view"),m("img",l.document.body).each(function(t,e){e.setAttribute("src",h(e.getAttribute("src")))}),o.customize&&o.customize(l,o,e);a=function(){o.autoPrint&&(l.print(),l.close())};navigator.userAgent.match(/Trident\/\d.\d/)?a():l.setTimeout(a,1e3)}else e.buttons.info(e.i18n("buttons.printErrorTitle","Unable to open print view"),e.i18n("buttons.printErrorMsg","Please allow popups in your browser for this site to be able to view the print view."),5e3)},title:"*",messageTop:"*",messageBottom:"*",exportOptions:{},header:!0,footer:!1,autoPrint:!0,customize:null},e});

View File

@@ -0,0 +1,4 @@
/*! DataTables Bootstrap 3 integration
* ©2011-2015 SpryMedia Ltd - datatables.net/license
*/
!function(t){"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function(e){return t(e,window,document)}):"object"==typeof exports?module.exports=function(e,a){return e=e||window,(a=a||("undefined"!=typeof window?require("jquery"):require("jquery")(e))).fn.dataTable||require("datatables.net")(e,a),t(a,0,e.document)}:t(jQuery,window,document)}(function(x,e,n,r){"use strict";var i=x.fn.dataTable;return x.extend(!0,i.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'p>>",renderer:"bootstrap"}),x.extend(i.ext.classes,{sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm",sProcessing:"dataTables_processing panel panel-default"}),i.ext.renderer.pageButton.bootstrap=function(d,e,o,a,l,u){function c(e,a){for(var t,n,r=function(e){e.preventDefault(),x(e.currentTarget).hasClass("disabled")||b.page()==e.data.action||b.page(e.data.action).draw("page")},i=0,s=a.length;i<s;i++)if(t=a[i],Array.isArray(t))c(e,t);else{switch(f=p="",t){case"ellipsis":p="&#x2026;",f="disabled";break;case"first":p=m.sFirst,f=t+(0<l?"":" disabled");break;case"previous":p=m.sPrevious,f=t+(0<l?"":" disabled");break;case"next":p=m.sNext,f=t+(l<u-1?"":" disabled");break;case"last":p=m.sLast,f=t+(l<u-1?"":" disabled");break;default:p=t+1,f=l===t?"active":""}p&&(n=-1!==f.indexOf("disabled"),n=x("<li>",{class:g.sPageButton+" "+f,id:0===o&&"string"==typeof t?d.sTableId+"_"+t:null}).append(x("<a>",{href:n?null:"#","aria-controls":d.sTableId,"aria-disabled":n?"true":null,"aria-label":w[t],"aria-role":"link","aria-current":"active"===f?"page":null,"data-dt-idx":t,tabindex:d.iTabIndex}).html(p)).appendTo(e),d.oApi._fnBindAction(n,{action:t},r))}}var p,f,t,b=new i.Api(d),g=d.oClasses,m=d.oLanguage.oPaginate,w=d.oLanguage.oAria.paginate||{};try{t=x(e).find(n.activeElement).data("dt-idx")}catch(e){}c(x(e).empty().html('<ul class="pagination"/>').children("ul"),a),t!==r&&x(e).find("[data-dt-idx="+t+"]").trigger("focus")},i});

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,85 @@
(function ($, oldFunction) {
$.param = function (a, traditional) {
var s = oldFunction.apply(oldFunction, [a, traditional]);
return s.replace(/\+/g, '%20');
};
})(jQuery, jQuery.param);
(function () {
'use strict';
angular
.module('smart.request', [])
.service('smartRequest', smartRequest);
smartRequest.$inject = ['$http', 'Notification', '$rootScope'];
function smartRequest($http, Notification, $rootScope) {
this.post = function (method, data, callback, error_callback, server_error_callback) {
var xsrf = $.param(data, true);
$http({
method: 'POST',
url: $rootScope.apiUrl + method,
timeout: 10 * 60 * 1000,
data: xsrf,
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Token': $rootScope.globals.currentUser ? $rootScope.globals.currentUser.token : '' }
}).then(function successCallback(response) {
if (response.data.status !== 'success') {
if (response.data.more) {
Notification.error(response.data.more);
}
if (response.data.message) {
Notification.error(response.data.message);
}
if (typeof error_callback !== typeof undefined) {
error_callback(response.data);
}
}
else {
if (typeof callback !== typeof undefined) {
callback(response.data);
}
}
}, function errorCallback(response) {
if (typeof server_error_callback !== typeof undefined) {
server_error_callback(response);
}
else {
Notification.error('Сервер недоступен');
}
});
};
this.get = function (method, callback, error_callback, server_error_callback) {
$http({
method: 'GET',
url: $rootScope.apiUrl + method,
timeout: 10 * 60 * 1000,
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Token': $rootScope.globals.currentUser ? $rootScope.globals.currentUser.token : '' }
}).then(function successCallback(response) {
if (response.data.status !== 'success') {
Notification.error(response.data.more);
if (typeof error_callback !== typeof undefined) {
error_callback(response.data);
}
}
else {
if (typeof callback !== typeof undefined) {
callback(response.data);
}
}
}, function errorCallback(response) {
if (typeof server_error_callback !== typeof undefined) {
server_error_callback(response);
}
else {
Notification.error('Сервер недоступен');
}
});
};
}
})();

View File

@@ -22,6 +22,10 @@
<link rel="stylesheet" href="../libs/angular/angular-ui-notification/dist/angular-ui-notification.min.css" />
<link rel="stylesheet" href="../assets/bootstrap/dist/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.3/css/dataTables.bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.3.5/css/buttons.dataTables.min.css" type="text/css" />
<!-- build:css ../assets/styles/app.min.css -->
<link rel="stylesheet" href="../assets/styles/app.css" type="text/css" />
@@ -29,21 +33,7 @@
<link rel="stylesheet" href="../assets/styles/font.css" type="text/css" />
<!-- Matomo -->
<script type="text/javascript">
var _paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.hrc.by/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
@@ -52,6 +42,17 @@
<!-- build:js scripts/app.angular.js -->
<!-- jQuery -->
<script src="../libs/jquery/jquery/dist/jquery.js"></script>
<!-- DataTables -->
<script src="../libs/datatables/jquery.dataTables.min.js"></script>
<script src="../libs/datatables/dataTables.buttons.min.js"></script>
<script src="../libs/datatables/buttons.print.min.js"></script>
<script src="../libs/datatables/pdfmake.min.js"></script>
<script src="../libs/datatables/vfs_fonts.js"></script>
<script src="../libs/datatables/buttons.html5.min.js"></script>
<script src="../libs/datatables/jszip.min.js"></script>
<script src="../libs/datatables/dataTables.bootstrap.min.js"></script>
<!-- Bootstrap -->
<script src="scripts/config.js"></script>

73
models/Base.php Normal file
View File

@@ -0,0 +1,73 @@
<?php
namespace App\Component\Models;
class Base
{
public static function tofloat($num) {
$dotPos = strrpos($num, '.');
$commaPos = strrpos($num, ',');
$sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos :
((($commaPos > $dotPos) && $commaPos) ? $commaPos : false);
if (!$sep) {
return floatval(preg_replace("/[^0-9]/", "", $num));
}
return floatval(
preg_replace("/[^0-9]/", "", substr($num, 0, $sep)) . '.' .
preg_replace("/[^0-9]/", "", substr($num, $sep+1, strlen($num)))
);
}
public static function validate_json($string)
{
// decode the JSON data
$result = json_decode(utf8_encode($string), true, JSON_INVALID_UTF8_SUBSTITUTE);
// switch and check possible JSON errors
switch (json_last_error()) {
case JSON_ERROR_NONE:
$error = ''; // JSON is valid // No error has occurred
break;
case JSON_ERROR_DEPTH:
$error = 'The maximum stack depth has been exceeded.';
break;
case JSON_ERROR_STATE_MISMATCH:
$error = 'Invalid or malformed JSON.';
break;
case JSON_ERROR_CTRL_CHAR:
$error = 'Control character error, possibly incorrectly encoded.';
break;
case JSON_ERROR_SYNTAX:
$error = 'Syntax error, malformed JSON.';
break;
// PHP >= 5.3.3
case JSON_ERROR_UTF8:
$error = 'Malformed UTF-8 characters, possibly incorrectly encoded.';
break;
// PHP >= 5.5.0
case JSON_ERROR_RECURSION:
$error = 'One or more recursive references in the value to be encoded.';
break;
// PHP >= 5.5.0
case JSON_ERROR_INF_OR_NAN:
$error = 'One or more NAN or INF values in the value to be encoded.';
break;
case JSON_ERROR_UNSUPPORTED_TYPE:
$error = 'A value of a type that cannot be encoded was given.';
break;
default:
$error = 'Unknown JSON error occured.';
break;
}
if ($error !== '') {
// throw the Exception or exit // or whatever :)
return false;
}
// everything is OK
return true;
}
}

104
models/Cache.php Normal file
View File

@@ -0,0 +1,104 @@
<?php
namespace App\Component\Models;
class Cache
{
public static function get($code, $plugin, $input)
{
unset($input['ip']);
unset($input['token']);
unset($input['admin_user_id']);
unset($input['host']);
$method = $input['method_name'];
unset($input['method_name']);
$dirname = CORE_PATH . '/../../Cache/' . $code . '/' . $plugin . '/';
if (!is_dir($dirname)) {
mkdir($dirname, 0777);
}
$filename = $method . ".tmp";
if (file_exists($dirname . $filename)) {
$caches = json_decode(file_get_contents($dirname . $filename), true);
foreach ($caches as $key => $cache) {
if ($cache['input'] == $input) {
return $cache['result'];
}
}
} else {
return false;
}
}
public static function store($code, $plugin, $input, $result)
{
unset($input['ip']);
unset($input['token']);
unset($input['admin_user_id']);
unset($input['host']);
$method = $input['method_name'];
unset($input['method_name']);
$data = [];
$info = array('input' => $input, 'result' => $result);
array_push($data, $info);
$dirname = CORE_PATH . '/../../Cache/' . $code . '/' . $plugin . '/';
if (!is_dir($dirname)) {
mkdir($dirname, 0777);
}
$filename = $method . ".tmp";
if (!file_exists($dirname . $filename)) {
$handle = fopen($dirname . $filename, 'w');
fputs($handle, json_encode($data));
fclose($handle);
return $result;
} else {
$handle = fopen($dirname . $filename, 'r');
$caches = fgets($handle);
fclose($handle);
$caches = json_decode($caches, true);
foreach ($caches as $key => $cache) {
if ($cache == $info) {
return $info['result'];
} else {
array_push($caches, $info);
$handle = fopen($dirname . $filename, 'w');
fputs($handle, json_encode($caches));
fclose($handle);
return $info['result'];
}
}
}
}
public static function clear($code, $plugin, $input, $type)
{
$dirname = CORE_PATH . '/../../Cache/' . $code . '/' . $plugin . '/';
if ($type == 'single') {
$method = $input['method_name'];
if (is_dir($dirname)) {
$filename = $method . ".tmp";
if (file_exists($dirname . $filename)) {
unlink($dirname . $filename);
return true;
} else {
return false;
}
} else {
return false;
}
}
if ($type == 'full') {
$files = glob($dirname."/*");
if (count($files) > 0) {
foreach ($files as $file) {
if (file_exists($file)) {
unlink($file);
}
}
return true;
} else {
return false;
}
}
}
}

View File

@@ -4,17 +4,20 @@ namespace App\Component\Models;
use Illuminate\Database\Eloquent\Model;
class Client extends Model {
protected $table = 'clients';
class Client extends Model
{
protected $table = 'clients';
/**
* Get clients phone.
*/
public function clientPhone() {
return $this->belongsTo('App\Component\Models\ClientsPhone', 'user_code', 'client_guid');
}
/**
* Get clients phone.
*/
public function clientPhone()
{
return $this->belongsTo('App\Component\Models\ClientsPhone', 'user_code', 'client_guid');
}
public static function getPhone($guid) {
public static function getPhone($guid)
{
$phone = ClientsPhone::where('client_guid', $guid)->first();
if (isset($phone)) {
$phone = $phone['phone'];
@@ -24,7 +27,8 @@ class Client extends Model {
return $phone;
}
public static function getEmail($guid) {
public static function getEmail($guid)
{
$email = ClientsEmail::where('client_guid', $guid)->first();
if (isset($email)) {
$email = $email['email'];
@@ -34,7 +38,8 @@ class Client extends Model {
return $email;
}
public static function getAddress($guid) {
public static function getAddress($guid)
{
$address = ClientsAddress::where('client_guid', $guid)->first();
if (isset($address)) {
$address = $address['address'];
@@ -44,17 +49,19 @@ class Client extends Model {
return $address;
}
public static function getBarcode($guid) {
$barcode = ClientsBarcode::where('client_guid', $guid)->first();
public static function getBarcode($guid)
{
$barcode = Client::where('user_code', $guid)->first();
if (isset($barcode)) {
$barcode = $barcode['value'];
$barcode = $barcode['barcode_start'];
} else {
$barcode = '';
}
return $barcode;
}
public static function getID($guid) {
public static function getID($guid)
{
$id = Client::where('client_guid', $guid)->first();
if (isset($id)) {
$id = $id['id'];
@@ -64,4 +71,16 @@ class Client extends Model {
return $id;
}
public static function getName($guid)
{
$client_name = Client::where('user_code', $guid)
->first();
if (isset($client_name)) {
$client_name = $client_name['name'];
} else {
$client_name = 'Связанный персонал не найден';
}
return $client_name;
}
}

View File

@@ -6,4 +6,14 @@ use Illuminate\Database\Eloquent\Model;
class ClientsGroup extends Model {
protected $table = 'client_groups';
public static function getID($guid) {
$id = ClientsGroup::where('code', $guid)->first();
if (isset($id)) {
$id = $id['id'];
} else {
$id = 0;
}
return $id;
}
}

View File

@@ -46,20 +46,44 @@ class ClientsPresale extends Model
/**
* Presale log.
*/
public static function presaleLog($guid, $value, $time, $staff_id)
public static function presaleLog($guid, $value, $time, $staff_id, $type, $order_id)
{
if ($value > 0) {
$action_name = 'Внесение аванса';
} else {
$action_name = 'Зачет аванса';
$action_type = $type;
if ($action_type == 21) {
$action_name = 'Поступил предварительный платеж через скидку в размере ' . $value . ' BYN через заказ №' . $order_id;
}
if ($action_type == 11) {
$action_name = 'Поступил предварительный платеж наличными в размере ' . $value . ' BYN';
}
if ($action_type == 13) {
$action_name = 'Поступил предварительный платеж безналичными в размере ' . $value . ' BYN';
}
if ($action_type == 12) {
$action_name = 'Поступил предварительный платеж кредитной картой в размере ' . $value . ' BYN';
}
if ($action_type == 14) {
$action_name = 'Возврат предварительного платежа наличными в размере ' . $value . ' BYN';
}
if ($action_type == 16) {
$action_name = 'Возврат предварительного платежа безналичными в размере ' . $value . ' BYN';
}
if ($action_type == 15) {
$action_name = 'Возврат предварительного платежа кредитной картой в размере ' . $value . ' BYN';
}
if ($action_type == 2) {
$action_name = 'Зачтен предварительный платеж в размере ' . $value . ' BYN через заказ №' . $order_id;
}
$action = new ClientsActions();
$action->action = $action_name;
$action->created = Carbon::createFromTimestampUTC($time)->timezone('Europe/Minsk');
$action->user_id = $guid;
$action->action_value = abs($value);
$action->action_type = 2;
$action->action_type = $action_type;
$action->order_id = $order_id;
$action->who = $staff_id;
$action->save();
return $action_name;
}
}

View File

@@ -25,6 +25,19 @@ class Dishes extends Model {
$dish_name = 'Связанный товар удален';
}
}
if ($dish_name == 'Связанный товар удален') {
$dish_name = Dishes::where('legacy_code', $data)->where('is_history', 0)->first();
if ($dish_name) {
$dish_name = $dish_name['name'];
} else {
$dish_name = Dishes::where('legacy_code', $data)->where('is_history', 1)->first();
if ($dish_name) {
$dish_name = $dish_name['name'];
} else {
$dish_name = 'Связанный товар удален';
}
}
}
return $dish_name;
}
@@ -59,4 +72,19 @@ class Dishes extends Model {
}
return $isServing;
}
public static function GetPrinterCode($data) {
$dish = Dishes::where('legacy_code', $data)->where('is_history', 0)->first();
if ($dish) {
$printer_code = $dish['printer_code'];
} else {
$dish = Dishes::where('legacy_code', $data)->where('is_history', 1)->first();
if ($dish) {
$printer_code = $dish['printer_code'];
} else {
$printer_code = 0;
}
}
return $printer_code;
}
}

View File

@@ -6,4 +6,6 @@ use Illuminate\Database\Eloquent\Model;
class ExchangeActions extends Model {
protected $table = 'exchange_actions';
}

View File

@@ -6,4 +6,9 @@ use Illuminate\Database\Eloquent\Model;
class ExchangeDeleted extends Model {
protected $table = 'exchange_deleted';
public function deletedActions() {
return $this->hasMany('App\Component\Models\ExchangeActions', 'order_position', 'item_id')
->where('exchange_actions.action_type', '=', 5);
}
}

View File

@@ -54,7 +54,7 @@ class ExchangeOrders extends Model
'cof' => $item['cof'],
'unit' => Units::getName($item['units_id']),
'amount' => round($item['sale_price'] * $item['count'], 2),
'discount' => round($discount, 2)
'discount' => round($discount)
);
$amount += round($item['sale_price'] * $item['count'], 2);
$full_price += round($realPrice,2);

36
models/Filesystem.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
namespace App\Component\Models;
class Filesystem
{
public static function GetCode($token)
{
$code = json_decode(base64_decode(urldecode($token)), true);
$unn = $code['unn'];
if ($code == '') {
$session_file = __DIR__ . "\\..\\..\\..\\Sessions\\" . $token . ".ini";
$session_data = parse_ini_file($session_file);
$unn = intval($session_data['unn']);
}
return $unn;
}
public static function ClearFolder($dir)
{
$d = opendir($dir);
while (($entry = readdir($d)) !== false) {
if ($entry != "." && $entry != "..") {
if (is_dir($dir . "/" . $entry)) {
self::ClearFolder($dir . "/" . $entry);
} else {
unlink($dir . "/" . $entry);
}
}
}
closedir($d);
rmdir($dir);
return true;
}
}

View File

@@ -5,5 +5,5 @@ namespace App\Component\Models;
use Illuminate\Database\Eloquent\Model;
class OrderBot extends Model {
protected $table = 'orderbot_storage';
protected $table = 'order_bot';
}

View File

@@ -0,0 +1,9 @@
<?php
namespace App\Component\Models;
use Illuminate\Database\Eloquent\Model;
class OrderBotStorage extends Model {
protected $table = 'orderbot_storage';
}

View File

@@ -12,4 +12,19 @@ class Printer extends Model {
* @var array
*/
protected $guarded = [];
public static function getName($data) {
$printer_name = Printer::where('code', $data)->where('is_history', 0)->first();
if ($printer_name) {
$printer_name = $printer_name['name'];
} else {
$printer_name = Printer::where('code', $data)->where('is_history', 1)->first();
if ($printer_name) {
$printer_name = $printer_name['name'];
} else {
$printer_name = 'Связанный принтер удален';
}
}
return $printer_name;
}
}

View File

@@ -59,7 +59,7 @@ class ShiftOnlineOrders extends Model
'cof' => $item['cof'],
'unit' => Units::getName($item['units_id']),
'amount' => round($item['sale_price'] * $item['count'], 2),
'discount' => round($discount, 0)
'discount' => round($discount)
);
$amount += round($item['sale_price'] * $item['count'], 2);
$full_price += round($realPrice,2);

View File

@@ -1,5 +1,5 @@
[info]
name=V1
version=2.26
version=2.27
[build]
version=2.26
version=2.27

View File

@@ -116,12 +116,10 @@
};
$scope.editClient = function (client, group) {
$scope.contextElement = client;
$scope.contextGroup = group;
$('#edit-client').modal('toggle');
console.log(client);
console.log($scope.contextGroup);
};
$scope.updateClient = function (group) {
@@ -135,6 +133,8 @@
address: $scope.contextElement.address,
email: $scope.contextElement.email,
barcode: $scope.contextElement.barcode,
is_special_price: $scope.contextElement.special_price,
is_employee: $scope.contextElement.employee,
task: 'update'
}, function (data) {
if (data.status == 'success') {
@@ -147,12 +147,11 @@
});
};
$scope.removeClient = function () {
$scope.removeClient = function (client) {
$('#client-confirm-delete').modal('toggle');
$('#edit-client').modal('toggle');
smartRequest.post('v1/client', {
id: $scope.contextElement.id,
id: client.id,
task: 'delete'
}, function (data) {
$scope.getGroups();
@@ -166,6 +165,40 @@
});
};
$scope.lockClient = function (client) {
smartRequest.post('v1/client', {
id: client.id,
task: 'lock'
}, function (data) {
//$scope.getGroups();
//$scope.openGroup($scope.currentGroup);
if (data.message) {
Notification.success(data.message);
$scope.openClientInfo(client);
}
if (data.error_message) {
Notification.error(data.error_message);
}
});
};
$scope.unlockClient = function (client) {
smartRequest.post('v1/client', {
id: client.id,
task: 'unlock'
}, function (data) {
//$scope.getGroups();
//$scope.openGroup($scope.currentGroup);
if (data.message) {
Notification.success(data.message);
$scope.openClientInfo(client);
}
if (data.error_message) {
Notification.error(data.error_message);
}
});
};
$scope.pager = function (currentPage) {
smartRequest.get('v1/clients?group_id=' + $scope.currentGroup + '&page=' + $scope.currentPage, function (data) {
$scope.clients = data.clients;
@@ -179,11 +212,17 @@
if ($scope.search.query.length === 0) {
$scope.openGroup({id: $scope.currentGroupId});
} else {
smartRequest.post('client/search', {
smartRequest.post('v1/client', {
task: 'search',
name: $scope.search.query
},
function (data) {
$scope.clients = data.clients;
if (data.clients.length > 0) {
Notification.success(data.message);
} else {
Notification.error(data.message);
}
});
}
};
@@ -229,7 +268,8 @@
address: $scope.newClient.address,
email: $scope.newClient.email,
barcode: $scope.newClient.barcode,
is_special_price: $scope.newClient.special_price
is_special_price: $scope.newClient.special_price,
is_employee: $scope.newClient.employee
}, function (data) {
$scope.pager($scope.currentGroup);
$scope.closeCard();
@@ -256,6 +296,7 @@
};
$scope.openClientInfo = function (client) {
$('#actions_tab').tab('show')
$scope.currentClientId = client.id;
$scope.isCreateNewGroup = false;
$scope.isCreateNewClient = false;

File diff suppressed because it is too large Load Diff

View File

@@ -1,150 +1,248 @@
(function() {
'use strict';
angular
.module('app')
.controller('ReportsCtrl', ReportsCtrl);
(function () {
'use strict';
angular
.module('app', ['ui.bootstrap', 'ui.utils'])
.controller('ReportsCtrl', ReportsCtrl);
ReportsCtrl.$inject = ['$scope', 'smartRequest', 'Notification'];
function ReportsCtrl($scope, smartRequest, Notification) {
var date = new Date();
ReportsCtrl.$inject = ['$scope', 'smartRequest', 'Notification'];
var formatted = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
function ReportsCtrl($scope, smartRequest, Notification) {
Number.prototype.toDivide = function () {
var float = String(this.toFixed(2));
if (float.length <= 6) return float;
var space = 0;
var number = '';
date.setDate(date.getDate() - 1);
for (var i = float.length - 1; i >= 0; i--) {
if (space == 3) {
number = ' ' + number;
space = 0;
}
number = float.charAt(i) + number;
space++;
}
var formatted_yesterday = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
return number;
};
var date = new Date();
$scope.report_delete = [];
$scope.report_realisation = [];
$scope.start_date = formatted_yesterday;
$scope.end_date = formatted;
$scope.report_id = 'realisation';
$scope.history = [];
$scope.statistic = {};
$scope.staffs = [];
$scope.printers = [];
var formatted = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
$scope.update = function() {
smartRequest.get('v1/reports', function(data) {
$scope.history = data.reports;
});
smartRequest.get('v1/settings?code=11', function (data) {
$scope.delete_shift_value = data.value;
});
};
date.setDate(date.getDate() - 1);
$scope.deleteReport = function (report) {
$('#preload-modal').modal();
Notification.primary('Дождитесь удаления! Страница обновится автоматически.');
smartRequest.post('v1/deletedata', {
value: 'delete_report',
report_id: report.id
}, function (data) {
$scope.status = data.status;
$scope.message = data.message;
if (data.status == 'success') {
Notification.success(data.message);
setTimeout(function() {
//location.reload();
$scope.update();
$('#preload-modal').modal('hide');
}, 1000);
}
if ($scope.status == 'error') {
Notification.error(data.message);
}
});
};
var formatted_yesterday = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
$scope.reportDelete = function() {
smartRequest.get('v1/datareport?type=deleted&start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function(data) {
$scope.report_delete = data.deleted;
$scope.report_delete.total_sum = data.total_sum;
$scope.report_delete.total_count = data.total_count;
$('#report-delete').modal();
}, function(data) {
$scope.update();
});
};
$scope.report_delete = [];
$scope.report_realisation = [];
$scope.start_date = formatted_yesterday;
$scope.end_date = formatted;
$scope.report_id = 'realisation';
$scope.history = [];
$scope.statistic = {};
$scope.staffs = [];
$scope.printers = [];
$scope.dataTableOpt = {
"aoSearchCols": [
null
],
"oLanguage": {
"sUrl": 'https://cdn.datatables.net/plug-ins/1.13.3/i18n/ru.json'
},
"searching": false,
"paging": false,
"info": false,
"order": [[1, 'desc']],
};
$scope.update = function () {
smartRequest.get('v1/reports', function (data) {
$scope.history = data.reports;
$('.modal-body').scrollTop(0);
});
smartRequest.get('v1/settings?code=11', function (data) {
$scope.delete_shift_value = data.value;
});
};
$scope.reportRealisation = function() {
smartRequest.get('report/realisation?start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function(data) {
$scope.report_realisation = data.printers;
$scope.return_printers = data.ret_prints;
$scope.report_realisation.total_count = data.total_count;
$scope.report_realisation.total_sum = data.total_sum;
$('#report-realisation').modal();
}, function(data) {
$scope.update();
});
};
$scope.deleteReport = function (report) {
$('#preload-modal').modal();
Notification.primary('Дождитесь удаления! Страница обновится автоматически.');
smartRequest.post('v1/deletedata', {
value: 'delete_report',
report_id: report.id
}, function (data) {
$scope.status = data.status;
$scope.message = data.message;
if (data.status == 'success') {
Notification.success(data.message);
setTimeout(function () {
//location.reload();
$scope.update();
$('#preload-modal').modal('hide');
}, 1000);
}
if ($scope.status == 'error') {
Notification.error(data.message);
}
});
};
$scope.reportStatistic = function() {
smartRequest.get('report/statistics?start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function(data) {
$scope.statistic = data.statistic;
$('#report-statistic').modal();
}, function(data) {
$scope.update();
});
};
$scope.closeModal = function (modalName) {
$scope.modalName = '#' + modalName;
$('.modal-body').scrollTop(0);
$($scope.modalName).modal('dispose');
return true;
};
$scope.reportStaff = function() {
smartRequest.get('v1/datareport?type=staff&start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function(data) {
$scope.staffs = data.staffs;
$('#report-staff').modal();
}, function(data) {
$scope.update();
});
};
$scope.prevModal = function (modalFromName, modalToName) {
$scope.modal_from = '#' + modalFromName;
$scope.modal_to = '#' + modalToName;
$($scope.modal_from).modal('hide');
$($scope.modal_to).modal('toggle');
};
$scope.reportPay = function() {
smartRequest.get('report/payment?start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function(data) {
$scope.printers = data.printers;
$('#report-payment').modal();
}, function(data) {
$scope.update();
});
};
$scope.reportOut = function () {
smartRequest.get('v1/outorders?start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.orders = data.orders;
$scope.total = data.total;
$('#report-out').modal();
}, function (data) {
$scope.update();
});
};
$scope.nextModal = function (modalFromName, modalToName) {
$scope.modal_from = '#' + modalFromName;
$scope.modal_to = '#' + modalToName;
$($scope.modal_from).modal('hide');
$($scope.modal_to).modal('toggle');
};
$scope.createReport = function() {
switch ($scope.report_id) {
case 'deleted': $scope.reportDelete(); break;
case 'realisation': $scope.reportRealisation(); break;
case 'statistics': $scope.reportStatistic(); break;
case 'staff': $scope.reportStaff(); break;
case 'pay': $scope.reportPay(); break;
case 'out': $scope.reportOut(); break;
}
};
$scope.getOrders = function (discount_id, modalFromName, modalToName) {
$scope.discount_id = discount_id;
$scope.orders_list = $scope.orders_info[discount_id].orders;
$scope.nextModal(modalFromName, modalToName);
};
$scope.archiveReport = function(type, start_date, end_date) {
$scope.report_id = type;
$scope.start_date = start_date;
$scope.end_date = end_date;
$scope.createReport();
};
$scope.getItems = function (order_id, opened, closed, modalFromName, modalToName) {
smartRequest.get('v1/clientorderinfo?order_id=' + order_id + '&opened=' + opened + '&closed=' + closed, function (data) {
$scope.order_info = data.info;
$scope.nextModal(modalFromName, modalToName);
});
};
$scope.popup = function(data) {
var mywindow = window.open();
mywindow.document.write(data);
mywindow.print();
mywindow.close();
};
$scope.reportDiscounts = function () {
$('#preload-modal').modal();
Notification.primary('Отчет формируется. Ожидайте.');
smartRequest.get('v1/datareport?type=discounts&start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.orders_info = data.orders_info;
$scope.orders_count = data.orders_count;
$scope.orders_full_sum = data.orders_full_sum;
$scope.orders_sale_sum = data.orders_sale_sum;
$scope.orders_order_sum = data.orders_order_sum;
$('#preload-modal').modal('hide');
$('#report-discounts').modal();
$scope.update();
});
};
$scope.printElem = function(elem) {
$scope.popup($('<div/>').append($(elem).clone()).html());
};
$scope.reportDelete = function () {
$('#preload-modal').modal();
Notification.primary('Отчет формируется. Ожидайте.');
smartRequest.get('v1/datareport?type=deleted&start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.report_delete = data.orders;
$scope.totalSum = data.totalSum;
$scope.totalCount = data.totalCount;
$('#preload-modal').modal('hide');
$('#report-delete').modal();
$scope.update();
});
};
$scope.update();
}
$scope.reportRealisation = function () {
smartRequest.get('v1/datareport?type=realisation&start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.update();
$scope.report_realisation = data.printers;
$scope.return_printers = data.ret_prints;
$scope.report_realisation.total_count = data.total_count;
$scope.report_realisation.total_sum = data.total_sum;
$('#report-realisation').modal();
});
};
$scope.reportStatistic = function () {
smartRequest.get('v1/datareport?type=statistic&start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.fiscal = data.fiscal;
$scope.realisation = data.realisation;
$scope.returns = data.returns;
$scope.cancellations = data.cancellations;
$scope.statistic = data.statistic;
$scope.presales = data.presales;
$scope.payments = data.payments;
$('#report-statistic').modal();
$scope.update();
});
};
$scope.reportStaff = function () {
smartRequest.get('v1/datareport?type=staff&start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.staffs = data.staffs;
$('#report-staff').modal();
$scope.update();
});
};
$scope.reportPay = function () {
smartRequest.get('report/payment?start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.printers = data.printers;
$('#report-payment').modal();
$scope.update();
});
};
$scope.reportOut = function () {
smartRequest.get('v1/outorders?start_date=' + encodeURIComponent($scope.start_date) + '&end_date=' + encodeURIComponent($scope.end_date), function (data) {
$scope.orders = data.orders;
$scope.total = data.total;
$('#report-out').modal();
$scope.update();
});
};
$scope.createReport = function () {
switch ($scope.report_id) {
case 'deleted':
$scope.reportDelete();
break;
case 'realisation':
$scope.reportRealisation();
break;
case 'statistics':
$scope.reportStatistic();
break;
case 'staff':
$scope.reportStaff();
break;
case 'pay':
$scope.reportPay();
break;
case 'out':
$scope.reportOut();
break;
case 'discounts':
$scope.reportDiscounts();
break;
}
};
$scope.archiveReport = function (type, start_date, end_date) {
$scope.report_id = type;
$scope.start_date = start_date;
$scope.end_date = end_date;
$scope.createReport();
};
$scope.popup = function (data) {
var mywindow = window.open();
mywindow.document.write(data);
mywindow.print();
mywindow.close();
};
$scope.printElem = function (elem) {
console.log(elem);
$scope.popup($('<div/>').append($(elem).clone()).html());
};
$scope.update();
}
})();

View File

@@ -1,246 +1,345 @@
(function () {
'use strict';
angular
.module('app')
.controller('ShiftsCtrl', ShiftsCtrl);
'use strict';
angular
.module('app')
.filter('curr', function () { //maybe we should take it to the filter folder
return function (input) {
if (typeof input == 'string') {
input = parseFloat(input.replace(/,/g, '.'));
}
var outputValue = input;
if (typeof outputValue !== 'undefined') {
return outputValue.toFixed(2);
} else {
return 0.00;
}
};
})
.controller('ShiftsCtrl', ShiftsCtrl);
ShiftsCtrl.$inject = ['$scope', '$filter', 'smartRequest', 'Notification'];
function ShiftsCtrl($scope, $filter, smartRequest, Notification) {
var date = new Date();
var formatted = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
date.setDate(date.getDate() - 1);
var formatted_yesterday = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
ShiftsCtrl.$inject = ['$scope', '$filter', 'smartRequest', 'Notification'];
$scope.start_date = formatted;
$scope.end_date = formatted_yesterday;
$scope.response = false;
$scope.shifts = [];
$scope.report_delete = [];
$scope.countOfPages = 1;
$scope.currentPage = 1;
$scope.statistic = {};
$scope.staffs = [];
$scope.parseFloat = parseFloat;
function ShiftsCtrl($scope, $filter, smartRequest, Notification) {
Number.prototype.toDivide = function() {
var float = String(this.toFixed(2));
if(float.length <= 6) return float;
var space = 0;
var number = '';
$scope.add = function() {
$scope.reImport = {};
$('#reImport').modal();
};
for(var i = float.length - 1; i >= 0; i--) {
if(space == 3) {
number = ' ' + number;
space = 0;
}
number = float.charAt(i) + number;
space++;
}
$scope.create = function() {
var start_date = document.getElementById("startDate").value;
var end_date = document.getElementById("endDate").value;
console.log(start_date, end_date);
smartRequest.get('v1/import?start_date=' + encodeURIComponent(start_date) + '&end_date=' + encodeURIComponent(end_date), function(data) {
$scope.response = data.message;
if (data.message == 'shifts not found') {
Notification.error('Смены не найдены');
} else {
Notification.success('Задача создана');
$scope.update();
}
});
$('#reImport').modal('toggle');
};
$scope.update = function () {
smartRequest.get('shift/list?page=' + $scope.currentPage, function (data) {
$scope.shifts = data.shifts;
$scope.countOfPages = data.pages;
$scope.pages = $scope.makePages();
});
smartRequest.get('v1/settings?code=11', function (data) {
$scope.delete_shift_value = data.value;
});
};
return number;
};
var date = new Date();
var formatted = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
date.setDate(date.getDate() - 1);
var formatted_yesterday = ('0' + date.getDate()).slice(-2) + '.' + ('0' + (date.getMonth() + 1)).slice(-2) + '.' + date.getFullYear();
$scope.deleteShift = function (shift) {
$('#preload-modal').modal();
Notification.primary('Дождитесь удаления! Страница обновится автоматически.');
smartRequest.post('v1/deletedata', {
value: 'delete_shift',
shift_id: shift.id
}, function (data) {
$scope.status = data.status;
$scope.message = data.message;
if (data.status == 'success') {
Notification.success(data.message);
setTimeout(function() {
//location.reload();
$scope.update();
$('#preload-modal').modal('hide');
}, 1000);
}
if ($scope.status == 'error') {
Notification.error(data.message);
}
});
};
$scope.start_date = formatted;
$scope.end_date = formatted_yesterday;
$scope.response = false;
$scope.shifts = [];
$scope.report_delete = [];
$scope.countOfPages = 1;
$scope.currentPage = 1;
$scope.statistic = {};
$scope.staffs = [];
$scope.parseFloat = parseFloat;
$scope.dataTableOpt = {
"aoSearchCols": [
null
],
"oLanguage": {
"sUrl": 'https://cdn.datatables.net/plug-ins/1.13.3/i18n/ru.json'
},
"searching": false,
"paging": false,
"info": false,
"order": [[1, 'desc']],
};
$scope.reportMerged = function (shift) {
smartRequest.get('v1/datareport?type=merge&shift_id=' + shift.id, function (data) {
$scope.report_merge = data.data;
$scope.report_merge.count = data.count;
$scope.report_merge.shift_id = data.shift_id;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-merge').modal();
});
};
$scope.add = function () {
$scope.reImport = {};
$('#reImport').modal();
};
$scope.create = function () {
var start_date = document.getElementById("startDate").value;
var end_date = document.getElementById("endDate").value;
console.log(start_date, end_date);
smartRequest.get('v1/import?start_date=' + encodeURIComponent(start_date) + '&end_date=' + encodeURIComponent(end_date), function (data) {
$scope.response = data.message;
if (data.message == 'shifts not found') {
Notification.error('Смены не найдены');
} else {
Notification.success('Задача создана');
$scope.update();
}
});
$('#reImport').modal('toggle');
};
$scope.closeModal = function (modalName) {
$scope.modalName = '#' + modalName;
$($scope.modalName).modal('dispose');
};
$scope.update = function () {
smartRequest.get('shift/list?page=' + $scope.currentPage, function (data) {
$scope.shifts = data.shifts;
$scope.countOfPages = data.pages;
$scope.pages = $scope.makePages();
$('.modal-body').scrollTop(0);
});
smartRequest.get('v1/settings?code=11', function (data) {
$scope.delete_shift_value = data.value;
});
};
$scope.deleteShift = function (shift) {
$('#preload-modal').modal();
Notification.primary('Дождитесь удаления! Страница обновится автоматически.');
smartRequest.post('v1/deletedata', {
value: 'delete_shift',
shift_id: shift.id
}, function (data) {
$scope.status = data.status;
$scope.message = data.message;
if (data.status == 'success') {
Notification.success(data.message);
setTimeout(function () {
//location.reload();
$scope.update();
$('#preload-modal').modal('hide');
}, 1000);
}
if ($scope.status == 'error') {
Notification.error(data.message);
}
});
};
$scope.prevModal = function (modalFromName, modalToName) {
$scope.modal_from = '#' + modalFromName;
$scope.modal_to = '#' + modalToName;
$($scope.modal_from).modal('hide');
$($scope.modal_to).modal('toggle');
};
$scope.nextModal = function (modalFromName, modalToName) {
$scope.modal_from = '#' + modalFromName;
$scope.modal_to = '#' + modalToName;
$($scope.modal_from).modal('hide');
$($scope.modal_to).modal('toggle');
};
$scope.getOrders = function (discount_id, modalFromName, modalToName) {
$scope.discount_id = discount_id;
$scope.orders_list = $scope.orders_info[discount_id].orders;
$scope.nextModal(modalFromName, modalToName);
};
$scope.getItems = function (order_id, opened, closed, modalFromName, modalToName) {
smartRequest.get('v1/clientorderinfo?order_id=' + order_id + '&opened=' + opened + '&closed=' + closed, function (data) {
$scope.order_info = data.info;
$scope.nextModal(modalFromName, modalToName);
});
};
$scope.reportDiscounts = function (shift) {
smartRequest.get('v1/datareport?type=discounts&shift_id=' + shift.id, function (data) {
$scope.orders_info = data.orders_info;
$scope.orders_count = data.orders_count;
$scope.orders_full_sum = data.orders_full_sum;
$scope.orders_sale_sum = data.orders_sale_sum;
$scope.orders_order_sum = data.orders_order_sum;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-discounts').modal();
$scope.update();
});
};
$scope.reportMerged = function (shift) {
smartRequest.get('v1/datareport?type=merge&shift_id=' + shift.id, function (data) {
$scope.report_merge = data.data;
$scope.report_merge.count = data.count;
$scope.report_merge.shift_id = data.shift_id;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-merge').modal();
});
};
$scope.reportMoved = function (shift) {
smartRequest.get('v1/datareport?type=move&shift_id=' + shift.id, function (data) {
$scope.report_move = data.data;
$scope.report_move.count = data.count;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-move').modal();
});
};
$scope.reportMoved = function (shift) {
smartRequest.get('v1/datareport?type=move&shift_id=' + shift.id, function (data) {
$scope.report_move = data.data;
$scope.report_move.count = data.count;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-move').modal();
});
};
$scope.reportSliced = function (shift) {
smartRequest.get('v1/datareport?type=slice&shift_id=' + shift.id, function (data) {
$scope.report_slice = data.data;
$scope.report_slice.count = data.count;
$scope.report_slice.shift_id = data.shift_id;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-slice').modal();
});
};
$scope.reportSliced = function (shift) {
smartRequest.get('v1/datareport?type=slice&shift_id=' + shift.id, function (data) {
$scope.report_slice = data.data;
$scope.report_slice.count = data.count;
$scope.report_slice.shift_id = data.shift_id;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-slice').modal();
});
};
$scope.reportDelete = function (shift) {
smartRequest.get('v1/datareport?type=deleted&shift_id=' + shift.id, function (data) {
$scope.report_delete = data.deleted;
$scope.report_delete.total_sum = data.total_sum;
$scope.report_delete.total_count = data.total_count;
$scope.reportDelete = function (shift) {
smartRequest.get('v1/datareport?type=deleted&shift_id=' + shift.id, function (data) {
if (data.totalCount > 0) {
$scope.report_delete = data.orders;
$scope.total_sum = data.totalSum;
$scope.total_count = data.totalCount;
$scope.shift_id = shift.id;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.update();
$('#shift-delete').modal();
$('#report-delete').modal();
});
};
} else {
Notification.error(data.message);
}
$scope.reportRealisation = function (shift) {
smartRequest.get('report/realisation?shift_id=' + shift.id, function (data) {
});
};
$scope.report_realisation = data.printers;
$scope.return_printers = data.ret_prints;
$scope.reportRealisation = function (shift) {
smartRequest.get('v1/datareport?type=realisation&shift_id=' + shift.id, function (data) {
$scope.report_realisation = data.printers;
$scope.return_printers = data.ret_prints;
$scope.report_realisation.total_count = data.total_count;
$scope.report_realisation.total_sum = data.total_sum;
$scope.report_realisation.total_count = data.total_count;
$scope.report_realisation.total_sum = data.total_sum;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.update();
$('#report-realisation').modal();
});
};
$('#report-realisation').modal();
});
};
$scope.reportStatistic = function (shift) {
smartRequest.get('v1/datareport?type=statistic&shift_id=' + shift.id, function (data) {
$scope.fiscal = data.fiscal;
$scope.realisation = data.realisation;
$scope.returns = data.returns;
$scope.cancellations = data.cancellations;
$scope.statistic = data.statistic;
$scope.presales = data.presales;
$scope.payments = data.payments;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.update();
$('#report-statistic').modal();
});
};
$scope.reportStatistic = function (shift) {
smartRequest.get('report/statistics?shift_id=' + shift.id, function (data) {
$scope.statistic = data.statistic;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.reportStaff = function (shift) {
smartRequest.get('v1/datareport?type=staff&shift_id=' + shift.id, function (data) {
$scope.staffs = data.staffs;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-statistic').modal();
});
};
$scope.update();
$('#report-staff').modal();
});
};
$scope.reportStaff = function (shift) {
smartRequest.get('v1/datareport?type=staff&shift_id=' + shift.id, function (data) {
$scope.staffs = data.staffs;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.reportPay = function (shift) {
smartRequest.get('report/payment?shift_id=' + shift.id, function (data) {
$scope.printers = data.printers;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$('#report-staff').modal();
});
};
$scope.update();
$('#report-payment').modal();
});
};
$scope.reportPay = function (shift) {
smartRequest.get('report/payment?shift_id=' + shift.id, function (data) {
$scope.reportOut = function (shift) {
smartRequest.get('v1/outorders?shift_id=' + shift.id, function (data) {
$scope.response = data.message;
if (data.message == 'false') {
Notification.error('Внешние заказы не найдены');
} else {
$scope.orders = data.orders;
$scope.shift = data.shift;
$scope.total = data.total;
$scope.printers = data.printers;
$scope.start_date = shift.opened;
$scope.end_date = shift.closed;
$scope.update();
$('#report-out').modal();
}
});
};
$('#report-payment').modal();
}, function (data) {
$scope.update();
});
};
$scope.reportOut = function (shift) {
smartRequest.get('v1/outorders?shift_id=' + shift.id, function (data) {
$scope.response = data.message;
if (data.message == 'false') {
Notification.error('Внешние заказы не найдены');
} else {
$scope.orders = data.orders;
$scope.shift = data.shift;
$scope.total = data.total;
$scope.restoreShift = function (shift) {
$('#preload-modal').modal();
Notification.primary('Дождитесь загрузки! Страница обновится автоматически.');
smartRequest.post('v1/restoreshift', {
shift_id: shift.id
}, function (data) {
$scope.status = data.status;
$scope.response = data.message;
if (data.status == 'success') {
Notification.success(data.message);
setTimeout(function () {
location.reload();
}, 1000);
}
if ($scope.status == 'error') {
Notification.error(data.message);
}
});
};
$('#report-out').modal();
}
$scope.popup = function (data) {
var mywindow = window.open();
mywindow.document.write(data);
}, function (data) {
$scope.update();
});
};
mywindow.print();
mywindow.close();
};
$scope.restoreShift = function (shift) {
$('#preload-modal').modal();
Notification.primary('Дождитесь загрузки! Страница обновится автоматически.');
smartRequest.post('v1/restoreshift', {
shift_id: shift.id
}, function (data) {
$scope.status = data.status;
$scope.response = data.message;
if (data.status == 'success') {
Notification.success(data.message);
setTimeout(function() {
location.reload();
}, 1000);
}
if ($scope.status == 'error') {
Notification.error(data.message);
}
});
};
$scope.printElem = function (elem) {
$scope.popup($('<div/>').append($(elem).clone()).html());
};
$scope.popup = function(data) {
var mywindow = window.open();
mywindow.document.write(data);
$scope.makePages = function () {
return Array.from({length: $scope.countOfPages}, (v, k) => k + 1);
};
mywindow.print();
mywindow.close();
};
$scope.showPage = function (index) {
$scope.currentPage = index;
$scope.update();
};
$scope.printElem = function(elem) {
$scope.popup($('<div/>').append($(elem).clone()).html());
};
$scope.nextPage = function () {
$scope.currentPage++;
$scope.update();
};
$scope.makePages = function () {
return Array.from({ length: $scope.countOfPages }, (v, k) => k + 1);
};
$scope.prevPage = function () {
$scope.currentPage--;
$scope.update();
};
$scope.showPage = function (index) {
$scope.currentPage = index;
$scope.update();
};
$scope.nextPage = function () {
$scope.currentPage++;
$scope.update();
};
$scope.prevPage = function () {
$scope.currentPage--;
$scope.update();
};
$scope.update();
}
$scope.update();
}
})();

271
web/controllers/staff.js Normal file
View File

@@ -0,0 +1,271 @@
(function() {
'use strict';
angular
.module('app')
.controller('StaffCtrl', StaffCtrl);
StaffCtrl.$inject = ['$scope', 'smartRequest', 'Notification', '$timeout'];
function StaffCtrl($scope, smartRequest, Notification, $timeout) {
$scope.groups = [];
$scope.personals = [];
$scope.parentGroup = 0;
$scope.parentGroupCode = '';
$scope.search = {
query: ''
};
$scope.interfaces = [];
$scope.rights = [];
$scope.currentPersonalObject = {
id: 0
};
$scope.currentGroupObject = {
id: 0
};
var promise = 0;
smartRequest.get('v1/clearcache?folder=staff', function () {});
$scope.update = function() {
smartRequest.get('staff/group/list', function(data) {
$scope.groups = data.groups;
});
};
$scope.updateGroups = function (callback, id) {
smartRequest.get('staff/group/list', function(data) {
$scope.groups = data.groups;
if (callback) {
var newGroup = $scope.getItemById($scope.groups, id);
callback(newGroup);
}
});
};
$scope.updatePersonals = function (callback, id) {
smartRequest.get('staff/list?group_code=' + $scope.parentGroupCode, function(data) {
$scope.personals = data.staff;
if (callback) {
var newStaff = $scope.getItemById($scope.personals, id);
callback(newStaff);
}
});
};
$scope.addGroup = function() {
smartRequest.post('staff/group/store', {
name: 'Новая группа'
}, function(data) {
var groupId = data.group_id;
$scope.updateGroups($scope.showGroup, groupId);
});
};
$scope.addPersonal = function() {
smartRequest.post('staff/store', {
name: 'Новый персонал',
group_code: $scope.parentGroupCode
}, function(data) {
var staffId = data.staff_id;
$scope.updatePersonals($scope.showPersonal, staffId);
});
};
$scope.openGroup = function(group) {
$scope.currentGroupObject = {
id: 0
};
$scope.parentGroup = group.id;
$scope.parentGroupCode = group.code;
$scope.personals = [];
$scope.updatePersonal();
};
$scope.showPersonal = function(personal) {
$scope.currentGroupObject = {
id: 0
};
$scope.currentPersonalObject = personal;
};
$scope.showGroup = function(group) {
$scope.currentPersonalObject = {
id: 0
};
$scope.currentGroupObject = group;
for(var i = 0; i < $scope.rights.length; i++) {
$scope.rights[i].is_active = false;
}
smartRequest.get('staff/right/list?group_code=' + $scope.currentGroupObject.code, function(data) {
for(var i = 0; i < data.rights.length; i++) {
for(var j = 0; j < $scope.rights.length; j++) {
if(data.rights[i].code === $scope.rights[j].code) {
$scope.rights[j].is_active = true;
break;
}
}
}
});
};
$scope.updatePersonal = function() {
smartRequest.get('staff/list?group_code=' + $scope.parentGroupCode, function(data) {
$scope.personals = data.staff;
});
};
$scope.closeCard = function() {
$scope.currentPersonalObject = {
id: 0
};
$scope.currentGroupObject = {
id: 0
};
};
$scope.getItemById = function(list, id) {
var res;
list.forEach(function (item) {
if (item.id == id) {
res = item;
return;
}
});
return res;
};
$scope.savePersonal = function() {
smartRequest.post('staff/update', {
id: $scope.currentPersonalObject.id,
name: $scope.currentPersonalObject.name,
password: $scope.currentPersonalObject.password,
interface_code: $scope.currentPersonalObject.interface_code,
group_code: $scope.currentPersonalObject.group_code
},
function(data) {
Notification.success('Персонал сохранен');
$scope.closeCard();
});
};
$scope.saveGroup = function() {
var activeRights = $scope.rights.filter(right => right.is_active);
smartRequest.post('staff/group/update', {
id: $scope.currentGroupObject.id,
name: $scope.currentGroupObject.name,
interface_code: $scope.currentGroupObject.interface_code,
sub_interface_code: $scope.currentGroupObject.sub_interface_code,
rights: JSON.stringify(activeRights.map(activeRight => activeRight.code))
}, function(data) {
Notification.success('Группа сохранена');
$scope.closeCard();
});
};
$scope.upFolder = function() {
$scope.currentPersonalObject = {
id: 0
};
$scope.currentGroupObject = {
id: 0
};
$scope.parentGroup = 0;
$scope.update();
};
$scope.removePersonal = function() {
$('#personal-confirm-delete').modal('toggle');
smartRequest.post('staff/delete', {
id: $scope.currentPersonalObject.id
}, function(data) {
$scope.currentPersonalObject = {
id: 0
};
$scope.updatePersonal();
});
};
$scope.removeGroup = function() {
$('#group-confirm-delete').modal('toggle');
smartRequest.post('staff/group/delete', {
id: $scope.currentGroupObject.id
}, function(data) {
$scope.currentGroupObject = {
id: 0
};
$scope.update();
});
};
$scope.personalSearch = function() {
if(promise){
$timeout.cancel(promise);
}
promise = $timeout(function() {
if($scope.search.query.length > 0) {
smartRequest.post('staff/search', {
name: $scope.search.query
},
function (data) {
$scope.personals = data.staff;
});
}
else {
$scope.upFolder();
}
}, 300);
};
$scope.setRights = function() {
$scope.removeActiveToggle();
$scope.onRightsByTemplate();
};
$scope.removeActiveToggle = function() {
$scope.rights.forEach(function (item) {
if (item.is_active) {
item.is_active = false;
}
});
};
$scope.onRightsByTemplate = function() {
smartRequest.get('staff/rights/template?code=' + $scope.currentGroupObject.interface_code + '&sub_code=' + $scope.currentGroupObject.sub_interface_code, function (data) {
for(var i = 0; i < data.rights.length; i++) {
for(var j = 0; j < $scope.rights.length; j++) {
if(data.rights[i].code === $scope.rights[j].code) {
$scope.rights[j].is_active = true;
break;
}
}
}
});
};
$scope.update();
smartRequest.get('staff/interface/list', function(data) {
$scope.interfaces = data.interfaces;
});
smartRequest.get('staff/right/all', function(data) {
$scope.rights = data.rights;
});
}
})();

View File

@@ -23,7 +23,7 @@
$scope.terminalLogs = [];
$scope.update = function () {
smartRequest.get('settings/terminals', function (data) {
smartRequest.get('v1/settings?method=terminals', function (data) {
$scope.terminals = data.terminals;
});
};

View File

@@ -35,6 +35,13 @@ item: [
order: 40
},
{
name: 'Персонал',
acl: 'staff',
url: 'app.staff',
icon: 'business',
order: 50
},
{
name: 'Реализация',
acl: 'shifts,report',
icon: 'library_books',

View File

@@ -46,6 +46,14 @@
controller: 'ClientsCtrl',
resolve: ['scripts/controllers/clients.js']
},
{
code: 'app.staff',
url: '/staff',
templateUrl: '../views/staff/index.html',
data: {title: 'Персонал'},
controller: 'StaffCtrl',
resolve: ['scripts/controllers/staff.js']
},
{
code: 'app.shifts',
url: '/shifts',

View File

@@ -4,26 +4,49 @@
<h5 class="modal-title">Редактирование клиента</h5>
</div>
<div class="modal-body p-lg">
<form role="form" class="ng-pristine ng-valid container">
<form role="form" class="ng-pristine ng-valid container" ng-submit="updateClient(contextGroup)">
<div class="form-group row">
<div class="col-sm-12">
<span>Группа: </span>
<select name="group" class="form-control input-c" ng-options="opt.id as opt.name for opt in groups" ng-model="contextGroup"></select>
<span>Имя: </span><input class="form-control" placeholder="Название" type="text" ng-model="contextElement.name">
<span>Телефон: </span><input class="form-control" type="text" ng-model="contextElement.phone" ui-mask="+375 (99) 999-99-99">
<span>Адрес: </span><input class="form-control" placeholder="Введите email" type="text" ng-model="contextElement.address">
<span>Email: </span><input class="form-control" placeholder="Введите адрес" type="text" ng-model="contextElement.email">
<span>Штрих код: </span><input class="form-control" placeholder="Введите штрих код" type="text" ng-model="contextElement.barcode">
</div>
<span>Группа: </span>
<select name="group" class="form-control input-c"
ng-options="opt.id as opt.name for opt in groups" ng-model="contextGroup"></select>
<span>Имя: </span><input class="form-control" placeholder="Название" type="text"
ng-model="contextElement.name">
<span>Телефон: </span><input class="form-control" type="text" ng-model="contextElement.phone"
ui-mask="+375 (99) 999-99-99">
<span>Адрес: </span><input class="form-control" placeholder="Введите email" type="text"
ng-model="contextElement.address">
<span>Email: </span><input class="form-control" placeholder="Введите адрес" type="text"
ng-model="contextElement.email">
<span>Штрих код: </span><input class="form-control" placeholder="Введите штрих код" type="text"
ng-model="contextElement.barcode">
<p>
<div class="form-group form-group-inline row">
<label class="col-sm-3 form-group-label" for="specialPriceCheck">Скидка по
себестоимости </label>
<div class="col-sm-9">
<input class="form-group-input" type="checkbox" value="" id="specialPriceCheck"
ng-model="contextElement.special_price" ng-checked="contextElement.special_price">
</div>
</div>
<div class="form-group form-group-inline row">
<label class="col-sm-3 form-group-label" for="employeeCheck">Сотрудник</label>
<div class="col-sm-9">
<input class="form-group-input" type="checkbox" value="" id="employeeCheck"
ng-model="contextElement.employee" ng-checked="contextElement.employee">
</div>
</div>
</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn dark-white p-x-md" data-dismiss="modal">Отмена</button>
<button type="submit" class="btn success p-x-md">Сохранить</button>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn danger p-x-md pull-left" data-toggle="modal" data-target="#client-confirm-delete"><i class="material-icons">&#xE872;</i></button>
<button type="button" class="btn dark-white p-x-md" data-dismiss="modal">Отмена</button>
<button type="button" class="btn success p-x-md" ng-click="updateClient(contextGroup)">Сохранить</button>
</div>
</div>
</div>

View File

@@ -103,44 +103,57 @@
<div class="p-a-md">
<div class="row m-t">
<div class="col-sm-12">
<a href="" class="pull-left m-r-md">
<div class="col-sm-11">
<a href="" class="pull-left m-r-md">
<span class="avatar w-96">
<img src="../views/clients/images/client.png">
<i class="on b-white"></i>
</span>
</a>
<div class="clear m-b">
<h3 class="m-0 m-b-xs">{{currentClient.name}}</h3>
<p class="text-muted">
</a>
<div class="clear m-b">
<h3 class="m-0 m-b-xs">{{currentClient.name}} <span ng-if="currentClient.info.is_block">(КЛИЕНТ ЗАБЛОКИРОВАН)</span></h3>
<p class="text-muted">
<span class="m-r">
<i class="fa fa-phone m-r-sm text-muted"></i>{{currentClient.info.phone}}
</span>
<small>
<i class="fa fa-map-marker m-r-xs"></i>{{currentClient.info.address}}
</small>
</p>
<small>
<i class="fa fa-map-marker m-r-xs"></i>{{currentClient.info.address}}
</small>
</p>
</div>
</div>
<div class="p-y text-center text-sm-center col-sm-12">
<a href="" class="inline p-x text-center">
<span class="h5 block m-0">{{currentClient.info.order_sum | curr}} BYN</span>
<small class="text-xs text-muted">Сумма заказов</small>
</a>
<a href="" class="inline p-x b-l text-center">
<span class="h5 block m-0">{{currentClient.info.order_count}}</span>
<small class="text-xs text-muted">Кол-во заказов</small>
</a>
<a href="" class="inline p-x b-l b-r text-center"
ng-if="currentClient.info.presale > 0">
<span class="h5 block m-0">{{currentClient.info.presale | curr}} BYN</span>
<small class="text-xs text-muted">Аванс</small>
</a>
<a href="" class="inline p-x text-center" ng-if="currentClient.info.bonus > 0">
<span class="h5 block m-0">{{currentClient.info.bonus}}</span>
<small class="text-xs text-muted">Бонусы</small>
</a>
<div class="col-sm-1">
<div class="dropdown inline">
<button class="btn white dropdown-toggle" data-toggle="dropdown"
aria-expanded="true"><i class="fa fa-bars"></i></button>
<div class="dropdown-menu dropdown-menu-scale pull-right">
<a class="dropdown-item" href="" ng-if="!currentClient.info.is_block" ng-click="lockClient(currentClient)">Заблокировать</a>
<a class="dropdown-item" href="" ng-if="currentClient.info.is_block" ng-click="unlockClient(currentClient)">Разблокировать</a>
<a class="dropdown-item" data-toggle="modal"
data-target="#client-confirm-delete">Удалить</a>
</div>
</div>
</div>
</div>
<div class="p-y text-center text-sm-center col-sm-12">
<a href="" class="inline p-x text-center">
<span class="h5 block m-0">{{currentClient.info.order_sum | curr}} BYN</span>
<small class="text-xs text-muted">Сумма заказов</small>
</a>
<a href="" class="inline p-x b-l text-center">
<span class="h5 block m-0">{{currentClient.info.order_count}}</span>
<small class="text-xs text-muted">Кол-во заказов</small>
</a>
<a href="" class="inline p-x b-l b-r text-center"
ng-if="currentClient.info.presale > 0">
<span class="h5 block m-0">{{currentClient.info.presale | curr}} BYN</span>
<small class="text-xs text-muted">Аванс</small>
</a>
<a href="" class="inline p-x text-center" ng-if="currentClient.info.bonus > 0">
<span class="h5 block m-0">{{currentClient.info.bonus}}</span>
<small class="text-xs text-muted">Бонусы</small>
</a>
</div>
</div>
</div>
</div>
@@ -148,17 +161,17 @@
<div class="row">
<div class="col-lg-12 col-sm-9">
<div class="p-y-md clearfix nav-active-primary">
<ul class="nav nav-pills nav-sm">
<ul class="nav nav-pills nav-sm" id="client_tab">
<li class="nav-item">
<a class="nav-link active" href="" data-toggle="tab" data-target="#tab_1"
<a class="nav-link active" id="actions_tab" href="" data-toggle="tab" data-target="#actions"
aria-expanded="true">Журнал действий</a>
</li>
<li class="nav-item">
<a class="nav-link" href="" data-toggle="tab" data-target="#tab_2"
<a class="nav-link" id="orders_tab" href="" data-toggle="tab" data-target="#orders"
aria-expanded="false" ng-click="getOrders(currentClient.id)">Заказы</a>
</li>
<li class="nav-item">
<a class="nav-link" href="" data-toggle="tab" data-target="#tab_3"
<a class="nav-link" id="info_tab" href="" data-toggle="tab" data-target="#info"
aria-expanded="false">Информация</a>
</li>
</ul>
@@ -170,19 +183,14 @@
<div class="row">
<div class="col-sm-8 col-lg-12">
<div class="tab-content">
<div class="tab-pane p-v-sm active" id="tab_1" aria-expanded="true">
<div class="tab-pane p-v-sm active" id="actions" aria-expanded="true">
<div class="streamline b-l m-b m-l"
style="width:auto;max-height:350px;overflow-y: auto;"
ng-if="clientLogs.length > 0">
<div class="sl-item b-success" ng-repeat="clientLog in clientLogs">
<div class="sl-content" ng-if="clientLog.type == 2">
<div class="sl-content">
<div class="sl-date text-muted">{{clientLog.time}}</div>
<p>{{clientLog.action}} на сумму {{clientLog.value | curr}} BYN
пользователем {{clientLog.who}}</p>
</div>
<div class="sl-content" ng-if="clientLog.type == 1">
<div class="sl-date text-muted">{{clientLog.time}}</div>
<p>{{clientLog.action}} в количестве {{clientLog.value}} шт</p>
<p>{{clientLog.action}}</p>
</div>
</div>
</div>
@@ -195,7 +203,7 @@
</div>
</div>
</div>
<div class="tab-pane p-v-sm" id="tab_2" aria-expanded="true">
<div class="tab-pane p-v-sm" id="orders" aria-expanded="true">
<div class="streamline b-l m-b m-l"
style="width:auto;max-height:350px;overflow-y: auto;"
ng-if="orders.length > 0">
@@ -231,7 +239,7 @@
</div>
</div>
</div>
<div class="tab-pane p-v-sm" id="tab_3">
<div class="tab-pane p-v-sm" id="info">
<div class="row m-b">
<div class="col-xs-10">
<small class="text-muted">Телефон:</small>
@@ -418,6 +426,14 @@
ng-model="newClient.special_price">
</div>
</div>
<div class="form-group form-group-inline row">
<label class="col-sm-3 form-group-label" for="employeeCheck">Сотрудник</label>
<div class="col-sm-9">
<input class="form-group-input" type="checkbox" value="" id="employeeCheck"
ng-model="newClient.employee">
</div>
</div>
</div>
<div class="dker p-a">
@@ -466,7 +482,7 @@
<div class="confirm-box-footer">
<button type="button" class="btn dark-white p-x-md" data-dismiss="modal">Нет</button>
<button type="button" class="btn danger p-x-md" ng-click="removeClient()">Да</button>
<button type="button" class="btn danger p-x-md" ng-click="removeClient(currentClient)">Да</button>
</div>
</div>
</div>

View File

@@ -16,12 +16,29 @@
<div class="padding">
<div class="margin">
<h5 class="m-b-0 _300">{{update_time}}
<i title="Данные о текущей смене скоро обновятся. Обновите страницу через несколько минут" class="fa fa-spinner fa-spin text-success" ng-if="need_update"></i>
</h5>
<small class="text-muted">Данные по филиалу
<strong>{{globals.currentUser.organization.name}}</strong>
</small>
<div class="row">
<div class="col-sm-9">
<h5 id="currentTime" class="m-b-0 _300">{{ currentDate | date:'dd.MM.yyyy HH:mm:ss' }}
</h5>
<small class="text-muted">Данные по филиалу
<strong>{{globals.currentUser.organization.name}}</strong>
</small>
</div>
<div class="col-sm-3">
<label class="md-switch">
<input id="timerCheckbox" type="checkbox" ng-model="timerEnabled" ng-change="toggleTimer()">
<i class="blue"></i>
<span ng-show="timerEnabled">
Автоматическое обновление через: {{ timeRemaining | date:'mm:ss' }}
</span>
<span ng-show="!timerEnabled">
Обновление данных отключено!
</span>
</label>
</div>
</div>
</div>
<div class="row">
@@ -113,7 +130,7 @@
<div class="box-tool box-tool-white">
<ul class="nav">
<li class="nav-item">
<a ng-click="getMore('delete')">
<a ng-click="getMoreDeleted()">
<i class="fa fa-eye"></i>
</a>
</li>
@@ -171,7 +188,7 @@
<div class="box-tool box-tool-white">
<ul class="nav">
<li class="nav-item">
<a ng-click="getMore('guests')">
<a ng-click="getMoreGuests()">
<i class="fa fa-eye"></i>
</a>
</li>
@@ -402,7 +419,7 @@
</div>
<div class="row">
<div class="col-md-12 col-xl-8" style="max-height: 620px; overflow-y: hidden;">
<div class="col-md-12 col-xl-8" style="max-height: 620px; "><!--overflow-y: hidden;-->
<div class="box">
<div class="box-header">
<h3>Топ продаваемых товаров</h3>
@@ -548,13 +565,13 @@
<div ui-include="'../views/dashboard/add.html'"></div>
</div>
<div class="modal fade" id="get-more-delete">
<div ui-include="'../views/dashboard/items/more-delete.html'"></div>
<div class="modal fade" id="get-more-deleted">
<div ui-include="'../views/dashboard/items/more-deleted.html'"></div>
</div>
<div class="modal my-modal fade" id="get-more-newyear">
<!--<div class="modal my-modal fade" id="get-more-newyear">
<div ui-include="'../views/dashboard/items/more-newyear.html'"></div>
</div>
</div>-->
<div class="modal fade" id="get-more-guests">
<div ui-include="'../views/dashboard/items/more-guests.html'"></div>
@@ -592,8 +609,8 @@
<div ui-include="'../views/dashboard/items/items-staff.html'"></div>
</div>
<div class="modal fade" id="items-delete">
<div ui-include="'../views/dashboard/items/items-delete.html'"></div>
<div class="modal fade" id="items-deleted">
<div ui-include="'../views/dashboard/items/items-deleted.html'"></div>
</div>
<div class="modal fade" id="preload-modal" data-backdrop="true">

View File

@@ -1,7 +1,7 @@
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-toggle="modal" data-target="#items-delete" ng-click="returnModal('delete')">
<button type="button" class="close" data-toggle="modal" data-target="#items-deleted" ng-click="returnModal('deleted')">
<i class="material-icons md-24">arrow_back</i>
</button>
<h5 class="modal-title">Подробнее об удалениях в заказе № {{ order.code }}</h5>

View File

@@ -17,7 +17,7 @@
</thead>
<tbody>
<tr ng-repeat="deleted_order in moreData.deleted_orders" ng-click="getItems('delete', deleted_order)">
<tr ng-repeat="deleted_order in moreData.deleted_orders" ng-click="getItemsDeleted(deleted_order)">
<td class="text-right">{{ deleted_order.number }}</td>
<td class="text-right">{{ deleted_order.opened }}</td>
<td class="text-right">{{ getClosedDate(deleted_order.closed) }}</td>
@@ -36,4 +36,5 @@
<div class="text-muted">Удаленных позиций нет</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -27,8 +27,8 @@
<thead>
<tr>
<th>Всего: {{ discounts }} {{ GetCountTotalOrders(discounts) }}</th>
<th class="text-right">на сумму {{ moreData.amount | curr }}</th>
<th class="text-right">со скидой в: {{discounts_sum | curr }}</th>
<th class="text-right">на сумму: {{ moreData.amount | curr }}</th>
<th class="text-right">со скидкой: {{discounts_sum | curr }}</th>
<th class="text-right">Итого: {{ moreData.total_sum | curr }} BYN</th>
</tr>
</thead>
@@ -40,4 +40,5 @@
</div>
</div>
</div>
</div>
</div>

View File

@@ -15,12 +15,13 @@
</tr>
</thead>
<tbody>
<tr ng-click="getItems('guests', client)">
<td class="text-right" style="width: 20%;">Заказ № {{ client.number }}</td>
<td class="text-right" style="width: 30%;">Открыт {{ client.opened }}</td>
<td class="text-right" style="width: 30%;">{{ client.closed }}</td>
<td class="text-right" style="width: 20%;">{{ client.sum | curr }} BYN</td>
<tbody ng-repeat="order in client.orders">
<tr ng-click="getItems('guests', order)">
<td class="text-right" style="width: 20%;">Заказ № {{ order.number }}</td>
<td class="text-right" style="width: 30%;">Открыт {{ order.opened }}</td>
<td ng-if="order.closed" class="text-right" style="width: 30%;">Закрыт {{ order.closed }}</td>
<td ng-if="!order.closed" class="text-right" style="width: 30%;">Не закрыт</td>
<td class="text-right" style="width: 20%;">{{ order.sum | curr }} BYN</td>
</tr>
</tbody>
</table>
@@ -31,4 +32,5 @@
<div class="text-muted">Заказов от именованных гостей нет</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -24,7 +24,7 @@
</div>
</div>
<div ng-if="client_name && client_address" class="form-group row">
<div ng-if="client_name" class="form-group row">
<div class="col-sm-6">
<input placeholder="Имя" ng-model="client_name" class="form-control" value="client_name" disabled></input>
<p>

View File

@@ -12,6 +12,7 @@
<option value="deleted">По удалениям</option>
<option value="pay">По отделам и видам оплат</option>
<option value="staff">По персоналу</option>
<option value="discounts">По скидкам</option>
<option value="out">По внешним заказам</option>
</optgroup>
</select>
@@ -130,6 +131,10 @@
<div ui-include="'../views/reports/items/deleted.html'"></div>
</div>
<div class="modal fade" id="report-discounts" data-backdrop="true">
<div ui-include="'../views/reports/items/discounts.html'"></div>
</div>
<div class="modal fade" id="report-realisation" data-backdrop="true">
<div ui-include="'../views/reports/items/realisation.html'"></div>
</div>
@@ -154,6 +159,14 @@
<div ui-include="'../views/shifts/preload.html'"></div>
</div>
<div class="modal fade" id="report-order-info" data-backdrop="true">
<div ui-include="'../views/reports/items/order-info.html'"></div>
</div>
<div class="modal fade" id="report-orders-list" data-backdrop="true">
<div ui-include="'../views/reports/items/orders-list.html'"></div>
</div>
<script type="text/javascript" src="/libs/js/moment/locale/ru.js"></script>
<script type="text/javascript">

View File

@@ -10,56 +10,84 @@
<span class="text-muted">{{start_date}} - {{end_date}}</span>
</div>
<div class="modal-body p-lg">
<div class="table-responsive" ng-if="report_delete.length > 0">
<table class="table table-bordered" ng-repeat="report in report_delete">
<thead>
<th>Смена#{{ report.shift_id }} Заказ #{{ report.order_code }}</th>
</thead>
<tbody>
<tr ng-repeat="item in report.items">
<td>
<h6>{{ item.dish_name }}
<small>
<p>Время удаления: <strong>{{item.time}}</strong></p>
<p>Цена товара: <strong>{{item.price}} BYN</strong></p>
<p>Количество: <strong>{{item.count}} шт</strong></p>
<p>На сумму: <strong>{{item.sum}} BYN</strong></p>
</small>
</h6>
<p>
Удалил:
<strong>{{ item.who }}</strong>
<br/> Подтвердил:
<strong>{{ item.approved }}</strong>
<br/> Причина:
<strong>{{ item.reason }}</strong>
</p>
</td>
</tr>
</tbody>
<hr>
</table>
<hr>
<table class="table table-bordered">
<tbody>
<tr>
<td>
<strong>Итого</strong>
</td>
<td style="text-align: right">
<strong>{{ report_delete.total_count }}</strong> удалений</td>
<td style="text-align: right">на сумму
<strong>{{ report_delete.total_sum | curr }} BYN</strong>
</td>
</tr>
</tbody>
</table>
<div ng-if="report_delete.length > 0">
<div class="m-b" id="shiftsAccordion">
<div class="panel box" ng-repeat="reportShift in report_delete">
<div class="box-header">
<span class="pull-right label text-sm">Удалено: {{reportShift.totalCount}} позиций. На сумму {{reportShift.totalSum | curr}} BYN</span>
<a data-toggle="collapse" data-parent="#accordion" data-target="#c_{{reportShift.shift_id}}"
class="collapsed" aria-expanded="false">
<h2>Смена №{{reportShift.shift_id}}</h2>
</a>
</div>
<div class="m-b" id="ordersAccordion">
<div id="c_{{reportShift.shift_id}}" class="panel box collapse" aria-expanded="false">
<div ng-repeat="reportOrder in reportShift.orders">
<div id="c_{{reportShift.shift_id}}_{{reportOrder.order_id}}" class="box-header">
<span class="pull-right label text-sm">Удалено: {{reportOrder.totalCount}} позиций. На сумму {{reportOrder.totalSum | curr}} BYN</span>
<a data-toggle="collapse" data-parent="#ordersAccordion"
data-target="#co_{{reportShift.shift_id}}_{{reportOrder.order_id}}"
class="collapsed" aria-expanded="false">
<h2>Заказ №{{reportOrder.order_id}}</h2>
</a>
</div>
<div id="co_{{reportShift.shift_id}}_{{reportOrder.order_id}}" class="collapse" aria-expanded="false">
<div class="box-body">
<div class="table-responsive-xl">
<table class="table table-bordered m-0">
<thead>
<tr>
<th>Имя</th>
<th>Время/Причина</th>
<th>Товар/цена</th>
<th>Кол-во</th>
<th>Итог</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in reportOrder.items">
<td>{{ item.who }}</td>
<td>
<ul class="list-unstyled">
<li>{{ item.time }}</li>
<li><small>{{ item.reason }}</small></li>
</ul>
</td>
<td>
<ul class="list-unstyled">
<li>{{ item.dish }}</li>
<li><small>{{ item.price | curr }} BYN</small></li>
</ul>
</td>
<td>{{ item.count }}</td>
<td>{{ item.total | curr}} BYN</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<table class="table table-bordered">
<tbody>
<tr>
<td>
<strong>Итого</strong>
</td>
<td style="text-align: right">
<strong>{{ totalCount }}</strong> удалений
</td>
<td style="text-align: right">на сумму
<strong>{{ totalSum | curr }} BYN</strong>
</td>
</tr>
</tbody>
</table>
<div ng-if="report_delete.length == 0">
<p>Удаления отсутствуют</p>
</div>

View File

@@ -0,0 +1,49 @@
<div class="modal-dialog modal-lg">
<div class="modal-content" id="report-discounts">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<button class="btn btn-icon white" ng-click="printElem('#report-discounts')">
<i class="fa fa-print"></i>
</button>
<h4 class="modal-title">{{globals.currentUser.organization.name}}</h4>
<h5 class="modal-title">Отчет по скидкам</h5>
<span class="text-muted">{{start_date}} - {{end_date}}</span>
</div>
<div class="modal-body p-lg">
<div class="table-responsive" ng-if="orders_count > 0">
<div class="table-responsive">
<p>Количество заказов со скидками: <strong>{{orders_count}}</strong><br>
Сумма заказов без скидок: <strong>{{orders_full_sum.toDivide()}} BYN</strong><br>
Сумма заказов со скидками: <strong>{{orders_order_sum.toDivide()}} BYN</strong><br>
Сумма скидок: <strong>{{orders_sale_sum.toDivide()}} BYN</strong>
</p>
<table class="table table-striped table-hover white b-a" ng-repeat="(discount_value, orders) in orders_info">
<thead>
<th>Скидка {{discount_value}}%</th>
</thead>
<thead>
<tr>
<th>Количество</th>
<th>Сумма заказов без скидки</th>
<th>Сумма заказов со скидкой</th>
<th>Сумма скидок</th>
</tr>
</thead>
<tbody>
<tr ng-click="getOrders(discount_value, 'report-discounts', 'report-orders-list')" data-toggle="tooltip" data-placement="bottom" title="Нажмите для просмотра списка заказов">
<td>{{orders.info.orders_count}}</td>
<td>{{orders.info.full_sum.toDivide()}} BYN</td>
<td>{{orders.info.order_sum.toDivide()}} BYN</td>
<td>{{orders.info.sale_sum.toDivide()}} BYN</td>
</tr>
</tbody>
</table>
</div>
</div>
<div ng-if="orders_count == 0">
<p>Заказы со скидками отсутствуют</p>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,78 @@
<div class="modal-dialog modal-lg">
<div class="modal-content" id="report-order-info">
<div class="modal-header">
<button type="button" class="close" ng-click="prevModal('report-order-info', 'report-orders-list')">
<i class="material-icons md-24">arrow_back</i>
</button>
<p>
Номер заказа: <strong>#{{order_info.order_id}}</strong><br>
Время закрытия: <strong>{{order_info.closed}}</strong><br>
Персонал: <strong>{{order_info.who_close}}</strong><br>
Статус заказа: <span class="label success">{{order_info.order_status}}</span><br>
</p>
</div>
<div class="modal-body p-lg">
<div class="table-responsive">
<table class="table table-striped white b-a">
<thead>
<tr>
<th>ID</th>
<th>Блюдо</th>
<th style="width: 80px">Кол-во</th>
<th style="width: 140px">Стоимость</th>
<th style="width: 180px">Итог</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in order_info.items">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.count * item.cof}}</td>
<td>{{item.price | curr}} BYN</td>
<td>{{item.amount | curr}} BYN <p ng-if="item.discount > 0">
<span>(Скидка: {{item.discount}}%)</span></p></td>
</tr>
<tr>
<td colspan="4" class="text-right"><strong>Итого</strong></td>
<td>{{order_info.amount | curr}} BYN</td>
</tr>
<tr>
<td colspan="4" class="text-right no-border"
ng-if="order_info.full_price - order_info.amount > 0">
<strong>Сумма скидки</strong></td>
<td ng-if="order_info.full_price - order_info.amount > 0">{{order_info.full_price -
order_info.amount | curr}} BYN
</td>
</tr>
<tr>
<td colspan="4" class="text-right no-border"><strong>Оплачено:</strong></td>
</tr>
<tr ng-if="order_info.cash > 0">
<td colspan="5" class="text-right no-border">Наличные: <strong>{{order_info.cash
| curr}} BYN</strong></td>
</tr>
<tr ng-if="order_info.credit > 0">
<td colspan="5" class="text-right no-border">Кред. карта: <strong>{{order_info.credit | curr}}
BYN</strong></td>
</tr>
<tr ng-if="order_info.clearing > 0">
<td colspan="5" class="text-right no-border">Питание штата: <strong>{{order_info.clearing |
curr}}
BYN</strong>
</tr>
<tr ng-if="order_info.presale > 0">
<td colspan="5" class="text-right no-border">Зачтен аванс: <strong>{{order_info.presale | curr}}
BYN</strong></td>
</tr>
<tr ng-if="order_info.self > 0">
<td colspan="5" class="text-right no-border">Безнал: <strong>{{order_info.self | curr}}
BYN</strong>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,44 @@
<div class="modal-dialog modal-lg">
<div class="modal-content" id="report-orders-list">
<div class="modal-header">
<button type="button" class="close" ng-click="prevModal('report-orders-list', 'report-discounts')">
<i class="material-icons md-24">arrow_back</i>
</button>
<h5 class="modal-title">Список заказов со скидкой {{discount_id}}%:</h5>
</div>
<div class="modal-body p-lg">
<div class="table-responsive" ng-if="orders_count > 0">
<div class="table-responsive">
<table class="table table-striped table-hover white b-a">
<thead>
<tr>
<th>Смена №</th>
<th>Заказ №</th>
<th>Сумма без скидки</th>
<th>Сумма со скидкой</th>
<th>Сумма скидки</th>
<th>Открыт</th>
<th>Закрыт</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="order in orders_list" ng-click="getItems(order.code, order.opened, order.closed, 'report-orders-list', 'report-order-info')" data-toggle="tooltip" data-placement="bottom" title="Нажмите для просмотра информации о заказе">
<td>{{order.shift_id}}</td>
<td>{{order.code}}</td>
<td>{{order.full_sum | curr}} BYN</td>
<td>{{order.order_sum | curr}} BYN</td>
<td>{{order.sale_sum | curr}} BYN</td>
<td>{{order.opened}}</td>
<td>{{order.closed}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div ng-if="orders_count == 0">
<p>Заказы со скидками отсутствуют</p>
</div>
</div>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<div class="modal-dialog modal-lg">
<div class="modal-content" id="reportRealisation">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<button type="button" class="close" data-dismiss="modal" ng-click="closeModal('reportRealisation')">&times;</button>
<button class="btn btn-icon white" ng-click="printElem('#reportRealisation')">
<i class="fa fa-print"></i>
</button>
@@ -9,9 +9,9 @@
<h5 class="modal-title">Отчет по реализации</h5>
<span class="text-muted">{{start_date}} - {{end_date}}</span>
</div>
<div class="modal-body p-lg">
<div id="tableRealisation" class="modal-body p-lg">
<div class="table-responsive" ng-if="report_realisation.length > 0">
<table class="table table-bordered" ng-repeat="printer in report_realisation">
<table class="table table-bordered table-striped datatable" ui-jq="dataTable" ui-options="dataTableOpt" ng-repeat="printer in report_realisation">
<thead>
<th style="width: 70%">{{ printer.name }}</th>
<th style="width: 10%; text-align: right">{{ printer.count }}</th>
@@ -26,9 +26,7 @@
</tr>
</tbody>
</table>
<div ng-if="return_printers.length > 0">
<hr>
<table class="table table-bordered" ng-repeat="ret_print in return_printers">
<thead>
<th style="width: 70%">{{ ret_print.name }} (возврат)</th>
@@ -46,8 +44,6 @@
</table>
</div>
<hr>
<table class="table table-bordered">
<tbody>
<tr>

View File

@@ -13,120 +13,171 @@
<div class="table-responsive">
<table class="table table-bordered">
<tbody>
<tr>
<td colspan="2">
<strong>Реализация</strong>
</td>
</tr>
<tr>
<td>Количество заказов</td>
<td style="text-align: right">{{ statistic.orders_count }}</td>
</tr>
<tr>
<td>Сумма заказов (без скидки) <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.total_sum | curr}}</td>
</tr>
<tr>
<td>Скидка <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.discount_sum | curr}}</td>
</tr>
<tr>
<td colspan="2">
<strong>Операции внесения/изъятия</strong>
</td>
</tr>
<tr>
<td>Внесено наличными</td>
<td style="text-align: right">{{ fiscal.income_sum | curr }} BYN</td>
</tr>
<tr>
<td>Выплачено наличными</td>
<td style="text-align: right">{{ fiscal.outcome_sum | curr }} BYN</td>
</tr>
<tr>
<td colspan="2">
<strong>Реализация</strong>
</td>
</tr>
<tr>
<td>Количество заказов</td>
<td style="text-align: right">{{ realisation.orders_count }}</td>
</tr>
<tr>
<td>Сумма заказов (без скидки)</td>
<td style="text-align: right">{{ realisation.orders_sum_without_sales | curr}} BYN</td>
</tr>
<tr>
<td>Скидка</td>
<td style="text-align: right">{{ realisation.sale_sum | curr}} BYN</td>
</tr>
<tr>
<td>Итоговоя сумма <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.orders_sum | curr}}</td>
</tr>
<tr>
<td>Отложенных заказы</td>
<td style="text-align: right">{{ statistic.wait_count }}</td>
</tr>
<tr>
<td>Отложено на сумму <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.wait_sum | curr}}</td>
</tr>
<tr>
<td>Итоговоя сумма</td>
<td style="text-align: right">{{ realisation.orders_sum_with_sales | curr}} BYN</td>
</tr>
<tr>
<td colspan="2">
<strong>Возвраты</strong>
</td>
</tr>
<tr>
<td>Количество возвратов</td>
<td style="text-align: right">{{ statistic.return_count }}</td>
</tr>
<tr>
<td>Сумма возвратов <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.return_sum | curr }}</td>
</tr>
<tr>
<td colspan="2">
<strong>Возвраты</strong>
</td>
</tr>
<tr>
<td>Количество возвратов</td>
<td style="text-align: right">{{ returns.returned_orders_count }}</td>
</tr>
<tr>
<td>Сумма возвратов</td>
<td style="text-align: right">{{ returns.returned_items_sum | curr }} BYN</td>
</tr>
<tr>
<td colspan="2">
<strong>Статистика</strong>
</td>
</tr>
<tr>
<td>Количество гостей</td>
<td style="text-align: right">{{ statistic.clients_count }}</td>
</tr>
<tr>
<td>Средний чек <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.avg_order_sum | curr}}</td>
</tr>
<tr>
<td>Средний чек на 1-го гостя <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.avg_order_client_sum | curr}}</td>
</tr>
<tr>
<td colspan="2">
<strong>Аннулирования</strong>
</td>
</tr>
<tr>
<td>Количество аннулирований</td>
<td style="text-align: right">{{ cancellations.cancellations_count }}</td>
</tr>
<tr>
<td>Сумма аннулирований</td>
<td style="text-align: right">{{ cancellations.cancellations_sum | curr }} BYN</td>
</tr>
<tr>
<td colspan="2">
<strong>Авансы</strong>
</td>
</tr>
<tr>
<td>Количество авансов полученных</td>
<td style="text-align: right">{{ statistic.in_presale_count }}</td>
</tr>
<tr>
<td>Сумма авансов полученных <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.in_presale_sum | curr}}</td>
</tr>
<tr>
<td>Количество авансов возвращенных</td>
<td style="text-align: right">{{ statistic.out_presale_count }}</td>
</tr>
<tr>
<td>Сумма авансов возвращенных <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.out_presale_sum | curr}}</td>
</tr>
<tr>
<td colspan="2">
<strong>Статистика</strong>
</td>
</tr>
<tr>
<td>Количество гостей</td>
<td style="text-align: right">{{ statistic.clients_count }}</td>
</tr>
<tr>
<td>Средний чек</td>
<td style="text-align: right">{{ statistic.clients_average_sum | curr}} BYN</td>
</tr>
<tr>
<td>Средний чек на 1-го гостя</td>
<td style="text-align: right">{{ statistic.clients_average_sum_one | curr}} BYN</td>
</tr>
<tr>
<td colspan="2">
<strong>Формы оплаты</strong>
</td>
</tr>
<tr>
<td>Наличный расчет <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.cash | curr}}</td>
</tr>
<tr>
<td>Наличный расчет (отложенные) <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.wait_sum | curr}}</td>
</tr>
<tr>
<td>Безналичный расчет <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.clearing | curr}}</td>
</tr>
<tr>
<td>Кредитными картами <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.credit | curr}}</td>
</tr>
<tr>
<td>Питание штата <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.self | curr}}</td>
</tr>
<tr>
<td>По ранее полученному авансу <strong>BYN</strong></td>
<td style="text-align: right">{{ statistic.presale | curr}}</td>
</tr>
<tr>
<td colspan="2">
<strong>Авансы</strong>
</td>
</tr>
<tr>
<td>Количество авансов полученных</td>
<td style="text-align: right">{{ presales.presales_income_count }}</td>
</tr>
<tr ng-if="presales.presales_income_cash_sum > 0">
<td>Сумма авансов полученных наличными</td>
<td style="text-align: right">{{ presales.presales_income_cash_sum | curr}} BYN</td>
</tr>
<tr ng-if="presales.presales_income_credit_sum > 0">
<td>Сумма авансов полученных кредитной картой</td>
<td style="text-align: right">{{ presales.presales_income_credit_sum | curr}} BYN</td>
</tr>
<tr ng-if="presales.presales_income_clearing_sum > 0">
<td>Сумма авансов полученных безналичным расчетом</td>
<td style="text-align: right">{{ presales.presales_income_clearing_sum | curr}} BYN</td>
</tr>
<tr ng-if="presales.presales_income_discount_sum > 0">
<td>Сумма авансов полученных через скидку</td>
<td style="text-align: right">{{ presales.presales_income_discount_sum | curr}} BYN</td>
</tr>
<tr>
<td>Количество авансов возвращенных</td>
<td style="text-align: right">{{ presales.presales_outcome_count }}</td>
</tr>
<tr ng-if="presales.presales_outcome_cash_sum > 0">
<td>Сумма авансов возвращенных наличными</td>
<td style="text-align: right">{{ presales.presales_outcome_cash_sum | curr}} BYN</td>
</tr>
<tr ng-if="presales.presales_outcome_credit_sum > 0">
<td>Сумма авансов возвращенных на кредитную карту</td>
<td style="text-align: right">{{ presales.presales_outcome_credit_sum | curr}} BYN</td>
</tr>
<tr ng-if="presales.presales_outcome_clearing_sum > 0">
<td>Сумма авансов возвращенных безналичным расчетом</td>
<td style="text-align: right">{{ presales.presales_outcome_clearing_sum | curr}} BYN</td>
</tr>
<tr>
<td colspan="2">
<strong>Формы оплаты</strong>
</td>
</tr>
<tr>
<td>Наличный расчет</td>
<td style="text-align: right">{{ payments.pay_cash | curr}} BYN</td>
</tr>
<tr>
<td>Кредитными картами</td>
<td style="text-align: right">{{ payments.pay_credit | curr}} BYN</td>
</tr>
<tr>
<td>Безналичный расчет</td>
<td style="text-align: right">{{ payments.pay_clearing | curr}} BYN</td>
</tr>
<tr>
<td>Питание штата</td>
<td style="text-align: right">{{ payments.pay_self | curr}} BYN</td>
</tr>
<tr>
<td>По ранее полученному авансу</td>
<td style="text-align: right">{{ payments.pay_presale | curr}} BYN</td>
</tr>
<tr>
<td>Онлайн</td>
<td style="text-align: right">{{ payments.pay_online | curr}} BYN</td>
</tr>
<tr>
<td>Иные способы оплаты</td>
<td style="text-align: right">{{ payments.pay_another | curr}} BYN</td>
</tr>
<tr ng-if="pay_delivery > 0">
<td>Доставка</td>
<td style="text-align: right">{{ payments.pay_delivery | curr}} BYN</td>
</tr>
<tr ng-if="pay_echeck > 0">
<td>Электронный чек</td>
<td style="text-align: right">{{ payments.pay_echeck | curr}} BYN</td>
</tr>
</tbody>
</table>

View File

@@ -57,6 +57,7 @@
<a class="dropdown-item" ng-click="reportDelete(shift)">По удалениям</a>
<a class="dropdown-item" ng-click="reportStaff(shift)">По персоналу</a>
<a class="dropdown-item" ng-click="reportPay(shift)">По отделам</a>
<a class="dropdown-item" ng-click="reportDiscounts(shift)">По скидкам</a>
<!-- <a class="dropdown-item" ng-click="reportOrders(shift)">По заказам</a> -->
<a class="dropdown-item" ng-click="reportMerged(shift)">По объединениям</a>
<a class="dropdown-item" ng-click="reportSliced(shift)">По разбиениям</a>
@@ -95,8 +96,8 @@
</div>
</div>
<div class="modal fade" id="report-delete" data-backdrop="true">
<div ui-include="'../views/reports/items/deleted.html'"></div>
<div class="modal fade" id="shift-delete" data-backdrop="true">
<div ui-include="'../views/shifts/items/deleted.html'"></div>
</div>
<div class="modal fade" id="report-realisation" data-backdrop="true">
@@ -137,4 +138,16 @@
<div class="modal fade" id="preload-modal" data-backdrop="true">
<div ui-include="'../views/shifts/preload.html'"></div>
</div>
<div class="modal fade" id="report-discounts" data-backdrop="true">
<div ui-include="'../views/reports/items/discounts.html'"></div>
</div>
<div class="modal fade" id="report-order-info" data-backdrop="true">
<div ui-include="'../views/reports/items/order-info.html'"></div>
</div>
<div class="modal fade" id="report-orders-list" data-backdrop="true">
<div ui-include="'../views/reports/items/orders-list.html'"></div>
</div>

View File

@@ -0,0 +1,83 @@
<div class="modal-dialog modal-lg">
<div class="modal-content" id="reportDeleted">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<button class="btn btn-icon white" ng-click="printElem('#reportDeleted')">
<i class="fa fa-print"></i>
</button>
<h4 class="modal-title">{{globals.currentUser.organization.name}}</h4>
<h5 class="modal-title">Отчет по удалениям</h5>
<span class="text-muted">{{start_date}} - {{end_date}}</span>
</div>
<div class="modal-body p-lg">
<div ng-if="report_delete.length > 0">
<div class="m-b" id="accordion">
<div class="panel box" ng-repeat="report in report_delete">
<div class="box-header">
<span class="pull-right label text-sm">Удалено: {{report.orderTotalCount}} позиций. На сумму {{report.orderTotalSum | curr}} BYN</span>
<a data-toggle="collapse" data-parent="#accordion" data-target="#c_{{report.order_id}}"
class="collapsed" aria-expanded="false">
<h2>Заказ №{{report.order_id}}</h2>
</a>
</div>
<div id="c_{{report.order_id}}" class="collapse" aria-expanded="false">
<div class="box-body">
<div class="table-responsive-xl">
<table class="table table-bordered m-0">
<thead>
<tr>
<th>Имя</th>
<th>Время/Причина</th>
<th>Товар/цена</th>
<th>Кол-во</th>
<th>Итог</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in report.items">
<td>{{ item.who }}</td>
<td>
<ul class="list-unstyled">
<li>{{ item.time }}</li>
<li><small>{{ item.reason }}</small></li>
</ul>
</td>
<td>
<ul class="list-unstyled">
<li>{{ item.dish }}</li>
<li><small>{{ item.price | curr }} BYN</small></li>
</ul>
</td>
<td>{{ item.count }}</td>
<td>{{ item.total | curr}} BYN</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<table class="table table-bordered">
<tbody>
<tr>
<td>
<strong>Итого</strong>
</td>
<td style="text-align: right">
<strong>{{ total_count }}</strong> удалений
</td>
<td style="text-align: right">на сумму
<strong>{{ total_sum | curr }} BYN</strong>
</td>
</tr>
</tbody>
</table>
<div ng-if="report_delete.length == 0">
<p>Удаления отсутствуют</p>
</div>
</div>
</div>
</div>

237
web/views/staff/index.html Normal file
View File

@@ -0,0 +1,237 @@
<div class="app-body-inner">
<div class="row-col row-col-xs b-b">
<div class="col-sm-3 col-md-2 light bg b-r">
<div class="row-col">
<div class="p-a-xs b-b">
<div class="input-group">
<span class="input-group-addon no-border no-bg">
<i class="fa fa-search"></i>
</span>
<input type="text" class="form-control no-border no-bg" placeholder="Поиск персонала..." ng-keyup="personalSearch()" ng-model="search.query">
<span class="input-group-addon no-border no-bg search-clear" ng-click="search.query = ''">
<i class="fa fa-times"></i>
</span>
</div>
</div>
<div class="row-row">
<div class="row-body scrollable hover">
<div class="row-inner">
<div class="list inset">
<div class="list-item pointer no_selection" ng-if="parentGroup > 0 && search.query.length === 0" ios-dblclick="upFolder()">
<div class="list-left">
<span class="w-30">
<i class="material-icons" style="font-size: 30px;">&#xE2C7;</i>
</span>
</div>
<div class="list-body" style="line-height: 30px">
...
</div>
</div>
<div class="list-item pointer no_selection" ng-repeat="group in groups" sglclick="showGroup(group)" ng-class="group.id == currentGroupObject.id ? 'active' : ''"
ios-dblclick="openGroup(group)" ng-if="parentGroup == 0 && search.query.length === 0">
<div class="list-left">
<span class="w-30">
<i class="material-icons" style="font-size: 30px;">&#xE2C7;</i>
</span>
</div>
<div class="list-body" style="line-height: 30px">
{{ group.name }}
</div>
</div>
<div class="list-item pointer no_selection" ng-repeat="personal in personals" ng-click="showPersonal(personal)" ng-class="personal.id == currentPersonalObject.id ? 'active' : ''"
ng-if="parentGroup > 0 || search.query.length > 0">
<div class="list-left">
<span class="w-30">
<i class="material-icons" style="font-size: 30px;">&#xE893;</i>
</span>
</div>
<div class="list-body" style="line-height: 30px">
{{ personal.name }}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="p-a b-t text-center">
<a class="btn btn-md btn-outline rounded b-info text-info" ng-click="addGroup()" ng-if="parentGroup == 0 && search.query.length === 0">
<i class="fa fa-plus fa-fw m-r-xs"></i>Группа
</a>
<a class="btn btn-md btn-outline rounded b-info text-info" ng-click="addPersonal()" ng-if="parentGroup > 0 && search.query.length === 0">
<i class="fa fa-plus fa-fw m-r-xs"></i>Персонал
</a>
</div>
</div>
</div>
<div class="col-sm-8 col-md-5">
<div class="row-col" ng-class="(currentGroupObject.id == 0)?'hide-object':''">
<div class="p-a-sm">
<div>
<a class="btn btn-sm white pull-right" ng-click="closeCard()">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="row-row">
<div class="row-body">
<div class="row-inner">
<div class="padding">
<div class="form-horizontal">
<div class="form-group row">
<label class="col-sm-3 form-control-label">Название</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="currentGroupObject.name">
</div>
</div>
<hr/>
<div class="form-group row">
<label class="col-sm-3 form-control-label">Режим работы</label>
<div class="col-sm-9">
<select class="form-control" ng-model="currentGroupObject.interface_code" ng-change="setRights()">
<option ng-repeat="interface in interfaces" value="{{ interface.code }}">{{ interface.name }}</option>
</select>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<label class="form-control-label">Шаблоны прав</label>
</div>
<div class="col-sm-9">
<label class="radio-inline ui-check ui-check-md">
<input type="radio" name="sub-interface" ng-change="setRights()" ng-model="currentGroupObject.sub_interface_code" value="1" class="has-value">
<i class="dark-white"></i>Администратор
</label>
<label class="radio-inline ui-check ui-check-md">
<input type="radio" name="sub-interface" ng-change="setRights()" ng-model="currentGroupObject.sub_interface_code" value="2" class="has-value">
<i class="dark-white"></i>Официант
</label>
</div>
</div>
<div class="table-responsive" style="background-color: #fff">
<table class="table table-bordered table-hover">
<thead>
<th>Право</th>
<th>Статус</th>
</thead>
<tbody>
<tr ng-repeat="right in rights">
<td>{{ right.name }}</td>
<td style="width: 90px">
<label class="ui-switch ui-switch-md m-t-xs">
<input type="checkbox" ng-model="right.is_active">
<i></i>
</label>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer-form">
<div class="padding" style="float: right; width: 100%; padding: 0.5rem 1.5rem">
<button class="btn danger p-x-md pull-left" data-toggle="modal" data-target="#group-confirm-delete">
<i class="fa fa-trash"></i>
</button>
<button class="btn success p-x-md pull-right" ng-click="saveGroup()" style="margin-right: 15px">Сохранить</button>
</div>
</div>
</div>
<div class="row-col" ng-class="(currentPersonalObject.id == 0)?'hide-object':''">
<div class="p-a-sm">
<div>
<a class="btn btn-sm white pull-right" ng-click="closeCard()">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="row-row">
<div class="row-body">
<div class="row-inner">
<div class="padding">
<div class="form-horizontal">
<div class="form-group row">
<label class="col-sm-3 form-control-label">Имя</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="currentPersonalObject.name">
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 form-control-label">Пароль</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="currentPersonalObject.password">
</div>
</div>
<!-- <div class="form-group row">
<label class="col-sm-3 form-control-label">Режим работы</label>
<div class="col-sm-9">
<select class="form-control" ng-model="currentPersonalObject.interface_code">
<option ng-repeat="interface in interfaces" value="{{ interface.code }}">{{ interface.name }}</option>
</select>
</div>
</div> -->
</div>
</div>
</div>
</div>
</div>
<div class="footer-form">
<div class="padding" style="float: right; width: 100%; padding: 0.5rem 1.5rem">
<button class="btn danger p-x-md pull-left" data-toggle="modal" data-target="#personal-confirm-delete">
<i class="fa fa-trash"></i>
</button>
<button class="btn success p-x-md pull-right" ng-click="savePersonal()" style="margin-right: 15px">Сохранить</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="personal-confirm-delete" class="modal confirm-box" data-backdrop="true">
<div class="bottom white b-b" style="height: 90px">
<div class="confirm-box-body p-lg">
<p>Вы действительно хотите удалить персонал?</p>
</div>
<div class="confirm-box-footer">
<button type="button" class="btn dark-white p-x-md" data-dismiss="modal">Нет</button>
<button type="button" class="btn danger p-x-md" ng-click="removePersonal()">Да</button>
</div>
</div>
</div>
<div id="group-confirm-delete" class="modal confirm-box" data-backdrop="true">
<div class="bottom white b-b" style="height: 90px">
<div class="confirm-box-body p-lg">
<p>Вы действительно хотите удалить группу?</p>
</div>
<div class="confirm-box-footer">
<button type="button" class="btn dark-white p-x-md" data-dismiss="modal">Нет</button>
<button type="button" class="btn danger p-x-md" ng-click="removeGroup()">Да</button>
</div>
</div>
</div>