--- /dev/null
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 57,
+ "identityHash": "5a5aa2f77594578d228d211d5e4406a6",
+ "entities": [
+ {
+ "tableName": "templates",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `regular_expression` TEXT NOT NULL, `test_text` TEXT, `transaction_description` TEXT, `transaction_description_match_group` INTEGER, `transaction_comment` TEXT, `transaction_comment_match_group` INTEGER, `date_year` INTEGER, `date_year_match_group` INTEGER, `date_month` INTEGER, `date_month_match_group` INTEGER, `date_day` INTEGER, `date_day_match_group` INTEGER, `is_fallback` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "regularExpression",
+ "columnName": "regular_expression",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "testText",
+ "columnName": "test_text",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "transactionDescription",
+ "columnName": "transaction_description",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "transactionDescriptionMatchGroup",
+ "columnName": "transaction_description_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "transactionComment",
+ "columnName": "transaction_comment",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "transactionCommentMatchGroup",
+ "columnName": "transaction_comment_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "dateYear",
+ "columnName": "date_year",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "dateYearMatchGroup",
+ "columnName": "date_year_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "dateMonth",
+ "columnName": "date_month",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "dateMonthMatchGroup",
+ "columnName": "date_month_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "dateDay",
+ "columnName": "date_day",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "dateDayMatchGroup",
+ "columnName": "date_day_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isFallback",
+ "columnName": "is_fallback",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "template_accounts",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `template_id` INTEGER NOT NULL, `acc` TEXT, `position` INTEGER NOT NULL, `acc_match_group` INTEGER, `currency` INTEGER, `currency_match_group` INTEGER, `amount` REAL, `amount_match_group` INTEGER, `comment` TEXT, `comment_match_group` INTEGER, `negate_amount` INTEGER, FOREIGN KEY(`template_id`) REFERENCES `templates`(`id`) ON UPDATE RESTRICT ON DELETE CASCADE , FOREIGN KEY(`currency`) REFERENCES `currencies`(`id`) ON UPDATE RESTRICT ON DELETE RESTRICT )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "templateId",
+ "columnName": "template_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "accountName",
+ "columnName": "acc",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "position",
+ "columnName": "position",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "accountNameMatchGroup",
+ "columnName": "acc_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "currency",
+ "columnName": "currency",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "currencyMatchGroup",
+ "columnName": "currency_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "amount",
+ "columnName": "amount",
+ "affinity": "REAL",
+ "notNull": false
+ },
+ {
+ "fieldPath": "amountMatchGroup",
+ "columnName": "amount_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "accountComment",
+ "columnName": "comment",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "accountCommentMatchGroup",
+ "columnName": "comment_match_group",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "negateAmount",
+ "columnName": "negate_amount",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "fk_template_accounts_template",
+ "unique": false,
+ "columnNames": [
+ "template_id"
+ ],
+ "createSql": "CREATE INDEX IF NOT EXISTS `fk_template_accounts_template` ON `${TABLE_NAME}` (`template_id`)"
+ },
+ {
+ "name": "fk_template_accounts_currency",
+ "unique": false,
+ "columnNames": [
+ "currency"
+ ],
+ "createSql": "CREATE INDEX IF NOT EXISTS `fk_template_accounts_currency` ON `${TABLE_NAME}` (`currency`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "templates",
+ "onDelete": "CASCADE",
+ "onUpdate": "RESTRICT",
+ "columns": [
+ "template_id"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ },
+ {
+ "table": "currencies",
+ "onDelete": "RESTRICT",
+ "onUpdate": "RESTRICT",
+ "columns": [
+ "currency"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "currencies",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `position` TEXT NOT NULL, `has_gap` INTEGER NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "position",
+ "columnName": "position",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hasGap",
+ "columnName": "has_gap",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "accounts",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`level` INTEGER NOT NULL, `profile` TEXT NOT NULL, `name` TEXT NOT NULL, `name_upper` TEXT NOT NULL, `parent_name` TEXT, `expanded` INTEGER NOT NULL DEFAULT 1, `amounts_expanded` INTEGER NOT NULL DEFAULT 0, `generation` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`profile`, `name`))",
+ "fields": [
+ {
+ "fieldPath": "level",
+ "columnName": "level",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "profile",
+ "columnName": "profile",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "nameUpper",
+ "columnName": "name_upper",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "parentName",
+ "columnName": "parent_name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "expanded",
+ "columnName": "expanded",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "1"
+ },
+ {
+ "fieldPath": "amountsExpanded",
+ "columnName": "amounts_expanded",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ },
+ {
+ "fieldPath": "generation",
+ "columnName": "generation",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "profile",
+ "name"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5a5aa2f77594578d228d211d5e4406a6')"
+ ]
+ }
+}
\ No newline at end of file
import net.ktnx.mobileledger.dao.TemplateHeaderDAO;
import net.ktnx.mobileledger.utils.MobileLedgerDatabase;
-@Database(version = 56, entities = {TemplateHeader.class, TemplateAccount.class, Currency.class,
+@Database(version = 57, entities = {TemplateHeader.class, TemplateAccount.class, Currency.class,
net.ktnx.mobileledger.db.Account.class
})
abstract public class DB extends RoomDatabase {
private Integer dateDay;
@ColumnInfo(name = "date_day_match_group")
private Integer dateDayMatchGroup;
+ @ColumnInfo(name = "is_fallback")
+ private boolean isFallback;
public TemplateHeader(@NotNull Long id, @NonNull String name,
@NonNull String regularExpression) {
this.id = id;
dateMonthMatchGroup = origin.dateMonthMatchGroup;
dateDay = origin.dateDay;
dateDayMatchGroup = origin.dateDayMatchGroup;
+ isFallback = origin.isFallback;
+ }
+ public boolean isFallback() {
+ return isFallback;
+ }
+ public void setFallback(boolean fallback) {
+ isFallback = fallback;
}
public String getTestText() {
return testText;
else
header.setDateYearMatchGroup(ph.getDateYearMatchGroup());
+ header.setFallback(ph.isFallback());
+
return header;
}
else if (p instanceof TemplateAccount) {
private PossiblyMatchedValue<Integer> dateMonth = PossiblyMatchedValue.withLiteralInt(null);
private PossiblyMatchedValue<Integer> dateDay = PossiblyMatchedValue.withLiteralInt(null);
private SpannableString testMatch;
+ private boolean isFallback;
private Header() {
super(Type.HEADER);
}
dateYear = new PossiblyMatchedValue<>(origin.dateYear);
dateMonth = new PossiblyMatchedValue<>(origin.dateMonth);
dateDay = new PossiblyMatchedValue<>(origin.dateDay);
+
+ isFallback = origin.isFallback;
}
private static StyleSpan capturedSpan() { return new StyleSpan(Typeface.BOLD); }
private static UnderlineSpan matchedSpan() { return new UnderlineSpan(); }
private static ForegroundColorSpan notMatchedSpan() {
return new ForegroundColorSpan(Color.GRAY);
}
+ public boolean isFallback() {
+ return isFallback;
+ }
+ public void setFallback(boolean fallback) {
+ this.isFallback = fallback;
+ }
public String getName() {
return name;
}
return Misc.equalStrings(name, o.name) && Misc.equalStrings(pattern, o.pattern) &&
Misc.equalStrings(testText, o.testText) &&
Misc.equalStrings(patternError, o.patternError) &&
- Objects.equals(testMatch, o.testMatch);
+ Objects.equals(testMatch, o.testMatch) && isFallback == o.isFallback;
}
public String getMatchGroupText(int group) {
if (compiledPattern != null && testText != null) {
else
result.setDateDayMatchGroup(dateDay.getMatchGroup());
+ result.setFallback(isFallback);
+
return result;
}
public SpannableString getTestMatch() {
}
};
b.transactionComment.addTextChangedListener(transactionCommentWatcher);
+
+ b.templateIsFallbackSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (updatePropagationDisabled)
+ return;
+
+ getItem().setFallback(isChecked);
+ b.templateIsFallbackText.setText(isChecked ? R.string.template_is_fallback_yes
+ : R.string.template_is_fallback_no);
+ });
+ final View.OnClickListener fallbackLabelClickListener =
+ (view) -> b.templateIsFallbackSwitch.toggle();
+ b.templateIsFallbackLabel.setOnClickListener(fallbackLabelClickListener);
+ b.templateIsFallbackText.setOnClickListener(fallbackLabelClickListener);
}
@NotNull
private TemplateDetailsItem.Header getItem() {
b.templateDetailsHeadScanQrButton.setOnClickListener(this::scanTestQR);
+ b.templateIsFallbackSwitch.setChecked(header.isFallback());
+ b.templateIsFallbackText.setText(
+ header.isFallback() ? R.string.template_is_fallback_yes
+ : R.string.template_is_fallback_no);
+
checkPatternError(header);
}
finally {
public class MobileLedgerDatabase extends SQLiteOpenHelper {
public static final MutableLiveData<Boolean> initComplete = new MutableLiveData<>(false);
public static final String DB_NAME = "MoLe.db";
- private static final int LATEST_REVISION = 56;
+ private static final int LATEST_REVISION = 57;
private static final String CREATE_DB_SQL = "create_db";
private final Application mContext;
android:id="@+id/transaction_comment_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/text_margin"
app:endIconMode="clear_text"
- app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/template_is_fallback_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/template_transaction_comment_source"
android:hint="@string/template_transaction_comment_hint"
/>
</com.google.android.material.textfield.TextInputLayout>
+ <TextView
+ android:id="@+id/template_is_fallback_label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="@string/template_is_fallback_label"
+ android:textAppearance="?attr/textAppearanceListItem"
+ app:layout_constraintBottom_toTopOf="@+id/template_is_fallback_text"
+ app:layout_constraintEnd_toStartOf="@id/template_is_fallback_switch"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/transaction_comment_layout"
+ />
+ <TextView
+ android:id="@+id/template_is_fallback_text"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:textAppearance="?attr/textAppearanceListItemSecondary"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/template_is_fallback_switch"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/template_is_fallback_label"
+ />
+ <com.google.android.material.switchmaterial.SwitchMaterial
+ android:id="@+id/template_is_fallback_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_constraintBottom_toBottomOf="@id/template_is_fallback_text"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="@id/template_is_fallback_label"
+ />
+
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
create unique index un_transaction_accounts_order on transaction_accounts(profile, transaction_id, order_no);
create table currencies(id integer not null primary key, name varchar not null, position varchar not null, has_gap integer not null);
-CREATE TABLE templates (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, regular_expression TEXT NOT NULL, test_text TEXT, transaction_description TEXT, transaction_description_match_group INTEGER, transaction_comment TEXT, transaction_comment_match_group INTEGER, date_year INTEGER, date_year_match_group INTEGER, date_month INTEGER, date_month_match_group INTEGER, date_day INTEGER, date_day_match_group INTEGER);
+CREATE TABLE templates (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, regular_expression TEXT NOT NULL, test_text TEXT, transaction_description TEXT, transaction_description_match_group INTEGER, transaction_comment TEXT, transaction_comment_match_group INTEGER, date_year INTEGER, date_year_match_group INTEGER, date_month INTEGER, date_month_match_group INTEGER, date_day INTEGER, date_day_match_group INTEGER, is_fallback INTEGER NOT NULL DEFAULT 0);
CREATE TABLE template_accounts(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, template_id INTEGER NOT NULL, acc TEXT, position INTEGER NOT NULL, acc_match_group INTEGER, currency INTEGER, currency_match_group INTEGER, amount REAL, amount_match_group INTEGER, comment TEXT, comment_match_group INTEGER, negate_amount INTEGER, FOREIGN KEY(template_id) REFERENCES templates(id) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY(currency) REFERENCES currencies(id) ON UPDATE RESTRICT ON DELETE RESTRICT);
create index fk_template_accounts_template on template_accounts(template_id);
create index fk_template_accounts_currency on template_accounts(currency);
--- /dev/null
+-- Copyright © 2021 Damyan Ivanov.
+-- This file is part of MoLe.
+-- MoLe is free software: you can distribute it and/or modify it
+-- under the term of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your opinion), any later version.
+--
+-- MoLe is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License terms for details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with MoLe. If not, see <https://www.gnu.org/licenses/>.
+
+-- add templates.is_fallback
+
+BEGIN TRANSACTION;
+
+alter table templates \
+add is_fallback integer default 0;
+
+COMMIT TRANSACTION;
\ No newline at end of file
<string name="template_account_keep_amount_sign">Без промяна на знака</string>
<string name="template_account_change_amount_sign">Обръщане на знака на сумата (от плюс на минус и от минус на плюс)</string>
<string name="template_account_negate_amount_label">Знак на сумата</string>
+ <string name="template_is_fallback_label">Резервен макет</string>
+ <string name="template_is_fallback_yes">Макетът ще се предлага за избор само ако няма друг макет, който да пасва и да не е маркиран като резервен</string>
+ <string name="template_is_fallback_no">Макетът не е резервен</string>
</resources>
<string name="template_account_keep_amount_sign">Sign will not be altered</string>
<string name="template_account_change_amount_sign">Amount sign will be changed (plus to minus; minus to plus)</string>
<string name="template_account_negate_amount_label">Change amount sign</string>
+ <string name="template_is_fallback_label">Fallback template</string>
+ <string name="template_is_fallback_yes">Template will be offered for selection only when no templates match that aren\'t marked as fallback templates</string>
+ <string name="template_is_fallback_no">Template is a primary, high priority one, not a catch-all</string>
</resources>