Исправления, автоклуб

This commit is contained in:
Ivan Murashov
2017-07-28 18:36:51 +03:00
parent e53ceb9ef0
commit 7207c6e247
16 changed files with 203 additions and 171 deletions

View File

@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dinect.checker"
android:versionCode="1"
android:versionName="0.0.5">
android:versionName="0.1">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
@@ -18,8 +18,8 @@
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application android:name="io.flutter.app.FlutterApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher_app">
<activity android:name="com.dinect.checker.activity.MainActivity"
<application android:name="io.flutter.app.FlutterApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher">
<activity android:name="com.dinect.checker.MainActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Black.NoTitleBar"
@@ -32,7 +32,7 @@
</intent-filter>
</activity>
<activity android:name="com.dinect.checker.activity.CameraActivity"
<activity android:name="com.dinect.checker.CameraActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme"/>

View File

@@ -1,4 +1,4 @@
package com.dinect.checker.activity;
package com.dinect.checker;
import android.support.v7.app.AppCompatActivity;
import android.content.pm.ActivityInfo;
@@ -64,7 +64,7 @@ import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import com.dinect.checker.activity.Utils;
import com.dinect.checker.Utils;
import com.dinect.checker.R;
public class CameraActivity extends AppCompatActivity implements Camera.PreviewCallback {
@@ -209,15 +209,11 @@ public class CameraActivity extends AppCompatActivity implements Camera.PreviewC
int result = mScanner.scanImage(barcode);
if (result != 0) {
mCamera.cancelAutoFocus();
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mPreviewing = false;
SymbolSet syms = mScanner.getResults();
for (Symbol sym : syms) {
String symData = sym.getData();
if (!TextUtils.isEmpty(symData) && Utils.isOnline(this)) {
mPreviewing = false;
requestUser(sym.getData());
break;
} else {
@@ -288,7 +284,6 @@ public class CameraActivity extends AppCompatActivity implements Camera.PreviewC
if (code == 200) {
try {
String s = response.body().string();
Log.d("kifio", s);
JSONArray users = new JSONArray(s);
if (users.length() > 0) {
Intent intent = new Intent();
@@ -325,7 +320,7 @@ public class CameraActivity extends AppCompatActivity implements Camera.PreviewC
private CameraActivity mActivity;
private String mCode = "";
private String mUrl = "https://pos-api-int.dinect.com/20130701/users?auto=";
private String mUrl = "http://pos-api-autoclub.dinect.com/20130701/users?auto=";
private String mCard = "";
private String mToken = "";
@@ -347,11 +342,8 @@ public class CameraActivity extends AppCompatActivity implements Camera.PreviewC
@Override
public void run() {
Log.d("kifio", mUrl);
Log.d("kifio", mToken);
Request request = new Request.Builder()
.addHeader("DM-Authorization", "dmapptoken 9fec83cdca38c357e6b65dbb17514cdd36bf2a08")
.addHeader("DM-Authorization", "dmapptoken bdea0f3ba9034b688019a7cac753d1209e2b227f")
.addHeader("Authorization", "dmtoken " + mToken)
.url(mUrl)
.build();

View File

@@ -1,4 +1,4 @@
package com.dinect.checker.activity;
package com.dinect.checker;
import android.content.Context;
import android.app.Activity;

View File

@@ -1,11 +1,12 @@
package com.dinect.checker.activity;
package com.dinect.checker;
import android.os.Bundle;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import android.content.Context;
import android.content.SharedPreferences;
import com.dinect.checker.activity.CameraActivity;
import com.dinect.checker.CameraActivity;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugin.common.MethodCall;
@@ -32,10 +33,9 @@ public class MainActivity extends FlutterActivity {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
final String INSTANCE_ID_CHANNEL = "com.dinect.checker/instance_id";
mPreferences = getPreferences(Context.MODE_PRIVATE);
mChannel = new MethodChannel(getFlutterView(), INSTANCE_ID_CHANNEL);
mChannel = new MethodChannel(getFlutterView(), "com.dinect.checker/instance_id");
mChannel.setMethodCallHandler(
new MethodCallHandler() {
@Override
@@ -73,19 +73,20 @@ public class MainActivity extends FlutterActivity {
mPreferences.edit().putInt(PREF_DOC_ID, docId).apply();
result.success(String.valueOf(docId));
break;
case "isOnline":
boolean online = Utils.isOnline(MainActivity.this);
if (!online) {
Toast.makeText(MainActivity.this, "Проверьте интернет соединение", Toast.LENGTH_SHORT).show();
}
result.success(online);
break;
case "getPosID":
String posId = mPreferences.getString(PREF_POS_ID, null);
if (posId == null) {
posId = String.valueOf(System.currentTimeMillis());
}
Log.d("kifio", posId);
mPreferences.edit().putString(PREF_POS_ID, posId).apply();
result.success(posId);
break;
default:
result.notImplemented();
@@ -119,15 +120,15 @@ public class MainActivity extends FlutterActivity {
}
}
private void handleItemClick() {
public void handleItemClick() {
}
private void getDocID() {
public void getDocID() {
}
private void removeKeys() {
public void removeKeys() {
}
@@ -159,4 +160,8 @@ public class MainActivity extends FlutterActivity {
}
public void isOnline() {
}
}

View File

@@ -1,4 +1,4 @@
package com.dinect.checker.activity;
package com.dinect.checker;
import android.content.Context;
import android.net.NetworkInfo;

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -40,10 +40,13 @@ class _RegistrationScreenState extends BaseState<FinishRegistrationScreen> {
]);
}
handleTap() {
// Если токен активирован, то открывается экран со сканером,
// Если нет, то отправляется запрос на проверку статуса токена.
handleTap() async {
if (_tokenActive) {
startScanner(context);
} else {
if (await platform.invokeMethod('isOnline')) {
checkTokenStatus(token).then((response) {
print(response.body);
@@ -60,6 +63,7 @@ class _RegistrationScreenState extends BaseState<FinishRegistrationScreen> {
});
}
}
}
@override Widget getTextWidget() {
return new Row(children: <Widget>[new Text(_merchantID != null ? _merchantID : '', style: new TextStyle(color: Colors.black, fontSize: 16.0))]);
@@ -92,7 +96,7 @@ class _RegistrationScreenState extends BaseState<FinishRegistrationScreen> {
/// Получаем текст сообщения, в зависимости от статуса активации.
getMessageString() {
return _tokenActive ? 'Программа активирована' : 'Запрос на активацию программы отправлен, дождитесь подтверждения активации администратором';
return _tokenActive ? tokenActiveMessage : tokenWaitMessage;
}
/// Фоновое изображение для сообщения.

View File

@@ -1,12 +1,14 @@
import 'package:flutter/material.dart';
// Serious constants
const String url = 'https://pos-api-int.dinect.com/20130701/';
const String appToken = '9fec83cdca38c357e6b65dbb17514cdd36bf2a08';
const String url = 'http://pos-api-autoclub.dinect.com/20130701/';
const String appToken = 'bdea0f3ba9034b688019a7cac753d1209e2b227f';
// Hints
// Texts
const String merchantIDHint = 'ID магазина';
const String posIDHint = 'Номер кассы';
const String tokenActiveMessage = 'Программа активирована';
const String tokenWaitMessage = 'Запрос на активацию программы отправлен, дождитесь подтверждения активации администратором';
// Assets
const String logo_png = 'assets/registration_logo.png';

View File

@@ -80,29 +80,49 @@ class FAQScreenState<T> extends BaseState<FAQScreen> {
];
static const String registrationGuide = '''
mPreviewing = true;После запуска приложения вы окажетесь на странице регистрации магазина.
Введите DIN код магазина (выдается партнером/менеджером International Auto Club, дублируется на почту)
Кликнете по кнопке: «Зарегистрировать»
Дождитесь подтверждение активации программы, кликом по кнопке «Обновите статус активации» обновите статус.
После подтверждения запроса на активацию программы Партнером/менеджером кликнете по кнопке «Завершить регистрацию», приложение готово к использованию.
После запуска приложения вы окажетесь на странице регистрации магазина.
При желании изменить номер кассы, необходимо кликнуть на «значок» верхнем правом углу и вернуться на шаг регистрации.
Введите DIN код магазина (выдается партнером/менеджером International Auto Club, дублируется на почту)
Кликните по кнопке: «Зарегистрировать»
Дождитесь подтверждение активации программы, кликом по кнопке «Обновите статус активации» обновите статус.
После подтверждения запроса на активацию программы Партнером/менеджером кликните по кнопке «Завершить регистрацию», приложение готово к использованию.
При желании изменить номер кассы, необходимо кликнуть на «значок» верхнем правом углу и вернуться на шаг регистрации.
''';
static const String usageGuide = '''Действие 1:
При предъявлении покупателем штрих кода участника системы лояльности, запустите данное приложение.
На экране появиться сканер штрих кодов. Поднесите гаджет к смартфону или карте покупателя и отсканируйте предъявленный штрих код сканером.
При успешном сканировании на вашем экране появятся данные партнера.
Действие 2:
Необходимо ввести сумму покупки данного покупателя и нажать на кнопку «Зафиксировать».
Всплывет окно “Подтверждения правильности ввода суммы” в случае правильного ввода суммы, нажмите “ДА”, сумма будет проведена и вознаграждение будет начислено участнику системы лояльности.
static const String usageGuide = '''
Действие 1:
Если же сумма введена с ошибкой, нажмите “НЕТ” вы вернетесь на шаг ввода суммы и скорректируете ее.''';
При предъявлении покупателем штрих-кода участника системы лояльности, запустите данное приложение.
static const String supportGuide = '''При некорректной работе приложения AUTO BONUS просьба сразу обратиться по телефону нашей технической поддержки: 8-800-234-6064 (звонок бесплатный), вас свяжут с менеджером. При звонке приготовьтесь назвать ИНН и наименование вашей организации.
Рекомендуйте покупателям установить мобильное приложение дисконтной системы International Auto Club AUTO BONUS, и получайте кэш бэк и их покупок в любых наземных или интернет магазинов.
Наш сайт https://www.auto-club.biz''';
На экране появится сканер штрих кодов. Отсканируйте предъявленный штрих-код сканером.
static const String commonGuide = '''Для эффективного считывания штрих кода участника системы лояльности необходимо камеру сканера поднести так, чтобы в неё не попадали вертикальные полосы рамки.
Долгое сканирование происходит из-за черной рамки, в которую помещен штрих-код, вертикальные полосы этой рамки расцениваются сканером как часть штрих-кода.''';
При успешном сканировании на вашем экране появятся данные партнера.
Действие 2:
Необходимо ввести сумму покупки данного покупателя и кликнуть по кнопке «Зафиксировать».
Всплывет окно подтверждения правильности ввода суммы». В случае правильного ввода суммы, кликните «ДА», сумма будет проведена и вознаграждение будет начислено участнику системы лояльности.
Если сумма введена с ошибкой, кликните «НЕТ» и Вы вернетесь на шаг ввода суммы и сможете её скорректировать.
''';
static const String supportGuide = '''
При некорректной работе приложения AUTO BONUS просьба сразу обратиться по телефону нашей технической поддержки: 8-800-234-6064 (звонок бесплатный) и Вас свяжут с менеджером.
При звонке приготовьтесь назвать ИНН и наименование вашей организации.
Рекомендуйте покупателям установить мобильное приложение дисконтной системы International Auto Club AUTO CLUB и получайте новых лояльных покупателей.
Наш сайт https://www.auto-club.biz
''';
static const String commonGuide = '''
Для эффективного считывания штрих-кода участника системы лояльности необходимо камеру сканера поднести так, чтобы в неё не попадали вертикальные полосы рамки.
Увеличение времени сканирования может произойти из-за черной рамки, в которую помещен штрих-код, так как вертикальные полосы этой рамки расцениваются сканером как часть штрих-кода.
''';
}

View File

@@ -24,12 +24,11 @@ class PurchaseScreen extends StatefulWidget {
class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
RegExp exp;
RegExp moneyRegexp = new RegExp(r'''^(?!0\.00)\d{1,11}(\.\d{0,2})?$''');
PurchaseScreenState(String userString, String card) {
this.user = JSON.decode(userString);
this.card = card;
exp = new RegExp(r'''^(?!0\.00)\d{1,11}(\.\d{0,2})?$''');
getLoyality(user['loyalty_url']);
}
@@ -72,7 +71,7 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
setState(() {
if (tmpString.length == 0 || exp.hasMatch(tmpString)) {
if (tmpString.length == 0 || moneyRegexp.hasMatch(tmpString)) {
if (tmpString.contains('.')) {
int dotIndex = tmpString.indexOf('.');
integerPart = tmpString.substring(0, dotIndex);
@@ -102,10 +101,9 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
onChanged: (text) => handleUserInput(text));
}
getLoyality(String url) {
getLoyality(String url) async {
print(url);
print(token);
if (await platform.invokeMethod('isOnline')) {
var headers = {
'DM-Authorization': 'dmapptoken 9fec83cdca38c357e6b65dbb17514cdd36bf2a08',
@@ -118,24 +116,18 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
Map bonuses = JSON.decode(response.body);
String type = bonuses['type'];
setState(() {
if (type == 'amount') {
this.loyality = '${user['discount']}%';
} else {
List amountToBonus = bonuses['amount_to_bonus'];
// print(amountToBonus[0]);
// print(amountToBonus[1]);
this.loyality = '${(amountToBonus[0] / double.parse(amountToBonus[1])).toStringAsFixed(0)}%';
}
});
}).catchError((error) {
print(error.toString());
});
}
}
_buildSum() {
@@ -175,7 +167,9 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
]));
}
purchase(String sum_total) {
purchase(String sum_total) async {
if (await platform.invokeMethod('isOnline')) {
platform.invokeMethod('getDocID').then((result) {
@@ -204,4 +198,5 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
});
});
}
}
}

View File

@@ -22,19 +22,29 @@ class _RegistrationScreenState extends BaseState<RegistrationScreen> {
return 'ID магазина';
}
/// Высота контейнера задана для того, чтобы элементы располагались вверху экрана
/// и список скроллился снизу вверх при открытии клавиатуры.
// Список виджетов, автоматически прокручиваемый вверх при открытии клавиатуры.
@override Widget getScreenContent() {
return new Container(
child: new ListView(children: <Widget>[
new Center(child: new Column(children: <Widget>[
new Column(children: <Widget>[
getLogo(),
getHintLabel(),
getDecoratedTextWidget(),
new Container(margin: new EdgeInsets.only(top: 36.0), child: buildRaisedButton(context, 'ЗАРЕГИСТРИРОВАТЬ', _isValidMerchantID() && !loading ? () => _registerShop(context) : null))]))
getButton()])
]));
}
// Возвращает кнопку регистрации.
getButton() {
return new Container(margin: new EdgeInsets.only(top: 36.0), child:
buildRaisedButton(context, 'ЗАРЕГИСТРИРОВАТЬ', getOnPressed()));
}
// Возвращает обработчик нажатий на кнопку регистрации.
getOnPressed() {
return _isValidMerchantID() && !loading ? () => _registerShop(context) : null;
}
/// Токен кассы - это DIN код. DIN код - это специальный код динекта, максимальная его длина - 25 символов.
_isValidMerchantID() {
print("${textFieldValue.length}");
@@ -51,7 +61,7 @@ class _RegistrationScreenState extends BaseState<RegistrationScreen> {
/// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена.
_register(BuildContext context) async {
if (await platform.invokeMethod('isOnline')) {
createToken(textFieldValue, await platform.invokeMethod('getPosID')).then((response) {
setState(() {
@@ -75,4 +85,5 @@ class _RegistrationScreenState extends BaseState<RegistrationScreen> {
print(error.toString());
});
}
}
}

View File

@@ -18,27 +18,28 @@ class SplashScreen extends StatelessWidget {
showNextScreen(context);
});
return new Stack(children: <Widget>[getBackgroundContainer(), getLogo(),
return new Stack(children: <Widget>[getSplashBackground(), getLogo(),
new Align(alignment: FractionalOffset.bottomRight, child:
new Container(margin: new EdgeInsets.only(right: 11.0, bottom: 5.0), child: new Image.asset(powered_by_dinect_splash_png, height: 16.0, width: 122.0)))]);
new Container(margin: new EdgeInsets.only(right: 11.0, bottom: 5.0), child:
new Image.asset(powered_by_dinect_splash_png, height: 16.0, width: 122.0)))]);
}
// Возвращает столбец с логотипом приложения и текстом под ним.
// Столбец занимает не все доступное пространство, а необходимый минимум в центре экрана.
getLogo() {
return new Center(child: new Column(mainAxisSize: MainAxisSize.min,
children: <Widget>[new Image.asset(logo_png, height: 112.0, width: 252.0),
new Image.asset(splash_text_png, height: 40.0, width: 240.0)]));
}
getBackgroundContainer() {
const margin = 48.0;
return new Container(padding: new EdgeInsets.only(left: margin, right: margin), decoration: getSplashBackground());
}
// Возвращает контейнер, который содержит decoration с фоновым изображением.
getSplashBackground() {
return new BoxDecoration(image: new DecorationImage(image: new ExactAssetImage(splash_png), fit: BoxFit.cover));
return new Container(decoration:
new BoxDecoration(image:
new DecorationImage(image: new ExactAssetImage(splash_png), fit: BoxFit.cover)));
}
/// Запуск следующего экрана приложения.
// Запуск следующего экрана приложения.
showNextScreen(BuildContext context) async {
token = await platform.invokeMethod('getToken');
@@ -49,6 +50,7 @@ class SplashScreen extends StatelessWidget {
if (token == null) {
pushRoute(context, new RegistrationScreen());
} else {
if (await platform.invokeMethod('isOnline')) {
checkTokenStatus(token).then((statusResponse) {
handleStatusResponse(context, statusResponse);
}).catchError((error) {
@@ -57,6 +59,7 @@ class SplashScreen extends StatelessWidget {
});
}
}
}
// Обработка ответа.
// В случае, если токен был удален может прийти active: false, либо 404.
@@ -78,9 +81,8 @@ class SplashScreen extends StatelessWidget {
if (active) {
startScanner(context);
} else {
if (await platform.invokeMethod('isOnline')) {
createToken(await platform.invokeMethod('getMerchantID'), await platform.invokeMethod('getPosID')).then((response) {
print('response.body: ${response.body}');
if (response.statusCode == 409) {
pushRoute(context, new FinishRegistrationScreen());
} else if (response.statusCode == 201) {
@@ -100,4 +102,5 @@ class SplashScreen extends StatelessWidget {
}
}
}
}
}