From c3bd061c4d97fa2ffbdadb272191bb85b3c0c584 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Tue, 22 Oct 2019 13:48:05 +0800 Subject: [PATCH 01/29] Deletion of receiptline (Approve by manager feature) --- src/container/ListingContainer/index.js | 8 ++ src/container/SalesContainer/index.js | 63 +++++++-- src/container/SettingsContainer/index.js | 6 +- src/store/PosStore/AttendantStore.js | 21 +++ src/store/PosStore/ItemStore.js | 1 + src/store/StateStore/DefaultValues.js | 1 + src/store/StateStore/Models.js | 1 + src/store/StateStore/StateStore.js | 8 +- .../components/AttendantsFormComponent.js | 22 ++- .../components/ConfirmationModalComponent.js | 126 ++++++++++++++++++ .../components/ModalKeypadComponent.js | 2 +- src/stories/screens/InputItem/frm.js | 3 + src/stories/screens/InputItem/index.js | 18 +++ src/stories/screens/Settings/index.js | 1 + 14 files changed, 266 insertions(+), 15 deletions(-) create mode 100644 src/stories/components/ConfirmationModalComponent.js diff --git a/src/container/ListingContainer/index.js b/src/container/ListingContainer/index.js index 2b4fc94..d215d7b 100644 --- a/src/container/ListingContainer/index.js +++ b/src/container/ListingContainer/index.js @@ -431,6 +431,7 @@ export default class ListingContainer extends React.Component { name: item.name, sku: item.sku, price: item.price, + tax: item.tax, soldBy: item.soldBy, barcode: item.barcode, description: item.name, @@ -451,6 +452,7 @@ export default class ListingContainer extends React.Component { description: item.name, soldBy: item.soldBy, price: unformat(item.price), + tax: unformat(item.tax), sku: item.sku, syncStatus: false, barcode: item.barcode, @@ -476,6 +478,7 @@ export default class ListingContainer extends React.Component { description: item.name, soldBy: item.soldBy, price: unformat(item.price), + tax: unformat(item.tax), sku: item.sku, barcode: item.barcode, category: item.category, @@ -500,6 +503,7 @@ export default class ListingContainer extends React.Component { soldBy: item.soldBy, price: item.price, sku: item.sku, + tax: item.tax, barcode: item.barcode, colorAndShape: item.colorAndShape, category: item.category, @@ -526,6 +530,7 @@ export default class ListingContainer extends React.Component { name: item.name, soldBy: item.soldBy, price: item.price, + tax: item.tax, sku: item.sku, barcode: item.barcode, colorAndShape: item.colorAndShape, @@ -545,6 +550,7 @@ export default class ListingContainer extends React.Component { name: item.name, soldBy: item.soldBy, price: unformat(item.price), + tax: unformat(item.tax), sku: item.sku, barcode: item.barcode, category: item.category, @@ -570,6 +576,7 @@ export default class ListingContainer extends React.Component { name: item.name, soldBy: item.soldBy, price: unformat(item.price), + tax: unformat(item.tax), sku: item.sku, barcode: item.barcode, category: item.category, @@ -595,6 +602,7 @@ export default class ListingContainer extends React.Component { name: item.name, soldBy: item.soldBy, price: item.price, + tax: item.tax, sku: item.sku, barcode: item.barcode, colorAndShape: item.colorAndShape, diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 91729e7..a11d7b4 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -22,6 +22,7 @@ import { } from "../../utils"; import PriceModalComponent from "@components/PriceModalComponent"; +import ConfirmationModalComponent from "@components/ConfirmationModalComponent"; import SummaryModalComponent from "@components/SummaryModalComponent"; import QuantityModalComponent from "@components/QuantityModalComponent"; import ConfirmOrderModalComponent from "@components/ConfirmOrderModalComponent"; @@ -222,12 +223,12 @@ export default class SalesContainer extends React.Component { }; onDeleteReceiptLine = () => { - const { hideDeleteDialog } = this.props.stateStore; - const { unselectReceiptLine, defaultReceipt } = this.props.receiptStore; + const { hideDeleteDialog } = this.props.stateStore; + hideDeleteDialog(); - unselectReceiptLine(); - defaultReceipt.clear(); - hideDeleteDialog(); + this.props.stateStore.changeConfirmation("AllReceiptLine"); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); }; onBarcodeClick = () => { @@ -568,10 +569,55 @@ export default class SalesContainer extends React.Component { // remove the receipt store this.props.stateStore.changeValue("quantityModalVisible", false, "Sales"); }; + execute_method = (pin) => { + const { changeValue } = this.props.stateStore; + this.props.attendantStore.findAttendantBasedOnRole(pin) + .then(result => { + changeValue("confirmation", false, "Sales"); + if (result) { + if (this.props.stateStore.currentConfirmation === "ReceiptLine"){ + + this.onReceiptLineDelete(this.props.stateStore.index_value); + } + else if (this.props.stateStore.currentConfirmation === "AllReceiptLine"){ + const { hideDeleteDialog } = this.props.stateStore; + const { unselectReceiptLine, defaultReceipt } = this.props.receiptStore; + unselectReceiptLine(); + defaultReceipt.clear(); + hideDeleteDialog(); + } + showToast("Successfully Deleted Receiptline(s)"); + + } else { + showToastDanger("Approvers Pin Invalid"); + } + }); + } + confirmationModal(){ + const { changeValue } = this.props.stateStore; + return ( + this.execute_method(pin)} + onClose={() => changeValue("confirmation", false, "Sales")} + /> + ); - onReceiptLineDelete = index => { - const { queueOrigin, currentTable } = this.props.stateStore; + } + showConfirmationModalReceiptLine = index => { + if (this.props.attendantStore.defaultAttendant.canApprove){ + this.onReceiptLineDelete(index); + } else { + this.props.stateStore.changeConfirmation("ReceiptLine"); + this.props.stateStore.changeIndex(index); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); + } + } + onReceiptLineDelete = (index) => { + const { queueOrigin, currentTable } = this.props.stateStore; this.props.receiptStore.unselectReceiptLine(); const receipt = this.props.receiptStore.defaultReceipt; @@ -858,6 +904,7 @@ export default class SalesContainer extends React.Component { {this.quantityEditDialog()} {this.priceInputDialog()} {this.onConfirmOrderDialog()} + {this.confirmationModal()} 0 ? parseInt(values.commission, 10) @@ -498,8 +499,6 @@ export default class SettingsContainer extends React.Component { } }); - // this.props.stateStore.changeValue("attendants", JSON.stringify(this.props.attendantStore.rows.slice()), "Settings") - // this.props.stateStore.changeValue("attendantsInfo",{}, "Settings") } else if (values.status === "Edit Attendant") { const valueAttendant = await this.props.attendantStore.find( values.id, @@ -511,6 +510,7 @@ export default class SettingsContainer extends React.Component { pin_code: values.pin, role: values.role, canLogin: values.canLogin, + canApprove: values.canApprove, commission: parseInt(values.commission, 10) > 0 ? parseInt(values.commission, 10) @@ -592,6 +592,7 @@ export default class SettingsContainer extends React.Component { pin_code: values.pin, role: values.role, canLogin: values.canLogin, + canApprove: values.canApprove, commission: parseInt(values.commission, 10) > 0 ? parseInt(values.commission, 10) @@ -629,6 +630,7 @@ export default class SettingsContainer extends React.Component { pin_code: values.pin, role: values.role, canLogin: values.canLogin, + canApprove: values.canApprove, commission: parseInt(values.commission, 10) > 0 ? parseInt(values.commission, 10) diff --git a/src/store/PosStore/AttendantStore.js b/src/store/PosStore/AttendantStore.js index 42b0fbc..16efd3a 100644 --- a/src/store/PosStore/AttendantStore.js +++ b/src/store/PosStore/AttendantStore.js @@ -19,6 +19,7 @@ export const Attendant = types user_name: types.string, pin_code: types.string, canLogin: types.optional(types.boolean, false), + canApprove: types.optional(types.boolean, false), role: types.optional(types.string, ""), dateUpdated: types.optional(types.Date, Date.now), syncStatus: types.optional(types.boolean, false), @@ -138,6 +139,7 @@ const AttendantStore = types pin_code: doc.pin_code, role: doc.role, canLogin: doc.canLogin ? doc.canLogin : false, + canApprove: doc.canApprove ? doc.canApprove : false, commission: doc.commission, dateUpdated: doc.dateUpdated, syncStatus: doc.syncStatus, @@ -180,6 +182,25 @@ const AttendantStore = types }); }); }, + findAttendantBasedOnRole(pin) { + + return new Promise(function(resolve, reject) { + db + .find({ + selector: { + canApprove: { $regex: true }, + pin_code: { $regex: pin }, + }, + }) + .then(result => { + if (result.docs.length > 0) { + resolve(true); + } else { + resolve(false); + } + }); + }); + }, })); const Store = AttendantStore.create({}); diff --git a/src/store/PosStore/ItemStore.js b/src/store/PosStore/ItemStore.js index 67c219a..7fb2d4c 100644 --- a/src/store/PosStore/ItemStore.js +++ b/src/store/PosStore/ItemStore.js @@ -24,6 +24,7 @@ export const Item = types description: types.optional(types.string, ""), soldBy: types.string, price: types.optional(types.number, 0), + tax: types.optional(types.number, 0), sku: types.optional(types.string, ""), barcode: types.union(types.string, types.number), colorAndShape: types.optional(types.string, ""), diff --git a/src/store/StateStore/DefaultValues.js b/src/store/StateStore/DefaultValues.js index ec4f836..080733f 100644 --- a/src/store/StateStore/DefaultValues.js +++ b/src/store/StateStore/DefaultValues.js @@ -22,6 +22,7 @@ export const sales = { fetching: false, addReceiptLineStatus: false, confirmOrder: false, + confirmation: false, commissionArray: JSON.stringify([]), }; export const listing = { diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index f042813..14c81ca 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -23,6 +23,7 @@ export const ModelSales = { discountSelectionStatus: types.optional(types.boolean, true), fetching: types.optional(types.boolean, false), confirmOrder: types.optional(types.boolean, false), + confirmation: types.optional(types.boolean, false), addReceiptLineStatus: types.optional(types.boolean, false), }; export const ModelListing = { diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index 6fb0b7c..1b73709 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -32,7 +32,8 @@ const StateStore = types currentTable: types.optional(types.number, -1), isViewingOrder: types.optional(types.boolean, false), isLoadingOrder: types.optional(types.boolean, false), - + currentConfirmation: types.optional(types.string, ""), + index_value: types.optional(types.number, 0), // Settings queueHost: types.optional(types.string, ""), hasTailOrder: types.optional(types.boolean, false), @@ -128,6 +129,11 @@ const StateStore = types }, setLoadingOrder(isLoadingOrder) { self.isLoadingOrder = isLoadingOrder; + }, + changeConfirmation(currentConfirmation) { + self.currentConfirmation = currentConfirmation; + },changeIndex(index) { + self.index_value = index; }, setOrders(orders) { self.orders = orders; diff --git a/src/stories/components/AttendantsFormComponent.js b/src/stories/components/AttendantsFormComponent.js index 2ad4cfd..01596d9 100644 --- a/src/stories/components/AttendantsFormComponent.js +++ b/src/stories/components/AttendantsFormComponent.js @@ -20,6 +20,7 @@ class AddAttendantComponent extends React.Component { status: "Save Attendant", role: "Owner", canLogin: false, + canApprove: false, commission: "", }; } @@ -59,6 +60,7 @@ class AddAttendantComponent extends React.Component { securityPinStatus: true, securityConfirmPinStatus: true, canLogin: attendantInfo.canLogin, + canApprove: attendantInfo.canApprove, commission: attendantInfo.commission.toString(), }); } else { @@ -72,6 +74,7 @@ class AddAttendantComponent extends React.Component { status: "Save Attendant", role: "Owner", canLogin: false, + canApprove: false, commission: "", }); } @@ -111,6 +114,10 @@ class AddAttendantComponent extends React.Component { const { canLogin } = this.state; this.setState({ canLogin: !canLogin }); }; + toggleCanApprove = () => { + const { canApprove } = this.state; + this.setState({ canApprove: !canApprove }); + }; onPress = () => { const { status } = this.state; @@ -201,7 +208,7 @@ class AddAttendantComponent extends React.Component { strings.setLanguage(currentLanguage().companyLanguage); const { rolesData } = this.props; - const { attendantName, role, canLogin } = this.state; + const { attendantName, role, canLogin, canApprove } = this.state; const Roles = rolesData.map(this.renderRoles); @@ -234,8 +241,17 @@ class AddAttendantComponent extends React.Component { /> {strings.CanLogin} - {canLogin ? this.renderPin() : null} - {canLogin ? this.renderConfirmPin() : null} + + + Can Approve + + {canLogin || canApprove ? this.renderPin() : null} + {canLogin || canApprove ? this.renderConfirmPin() : null} diff --git a/src/stories/components/ConfirmationModalComponent.js b/src/stories/components/ConfirmationModalComponent.js new file mode 100644 index 0000000..b88f52a --- /dev/null +++ b/src/stories/components/ConfirmationModalComponent.js @@ -0,0 +1,126 @@ +import * as React from "react"; +import { Modal, View, TouchableOpacity, StyleSheet } from "react-native"; +import { Text, Form, Item, Input, Button } from "native-base"; +import Icon from "react-native-vector-icons/MaterialCommunityIcons"; +import { currentLanguage } from "../../translations/CurrentLanguage"; + +import ModalKeypadComponent from "./ModalKeypadComponent"; +import translation from "../.././translations/translation"; +import LocalizedStrings from "react-native-localization"; +let strings = new LocalizedStrings(translation); +export default class ConfirmationModalComponent extends React.Component { + constructor(props) { + super(props); + this.state = { + pin: "", + }; + } + + onRequestClose = () => null; + + onNumberPress = text => { + + this.setState({ pin: this.state.pin.concat(text)}); + }; + + onDeletePress = () => { + this.setState({ pin: this.state.pin.slice(0, -1) }); + }; + + onSubmit = () => { + const pin = parseFloat(this.state.pin); + + this.setState({ pin: "" }); + this.props.onSubmit(pin); + }; + + render() { + strings.setLanguage(currentLanguage().companyLanguage); + return ( + + + + + Approvers Pin + this.props.onClose()} + > + + + + + +
+ + + +
+ + +
+
+
+ ); + } +} + +const styles = StyleSheet.create({ + view: { + flex: 1, + alignItems: "center", + flexDirection: "column", + justifyContent: "center", + backgroundColor: "#00000090", + }, + innerView: { + width: 240, + backgroundColor: "white", + }, + headerView: { + padding: 10, + borderBottomWidth: 0.5, + borderBottomColor: "#eee", + flexDirection: "row", + justifyContent: "space-between", + }, + headerText: { + color: "gray", + fontWeight: "bold", + }, + close: { + alignSelf: "flex-end", + }, + item: { + backgroundColor: "#eee", + }, + input: { + paddingRight: 15, + fontWeight: "bold" + }, + setButton: { + borderRadius: 0, + }, +}); + diff --git a/src/stories/components/ModalKeypadComponent.js b/src/stories/components/ModalKeypadComponent.js index 0155c10..046988c 100644 --- a/src/stories/components/ModalKeypadComponent.js +++ b/src/stories/components/ModalKeypadComponent.js @@ -44,7 +44,7 @@ export default class ModalKeypadComponent extends React.PureComponent { - + {"noPeriod" in this.props ? null} /> : ()} diff --git a/src/stories/screens/InputItem/frm.js b/src/stories/screens/InputItem/frm.js index d9a97d7..9552c10 100644 --- a/src/stories/screens/InputItem/frm.js +++ b/src/stories/screens/InputItem/frm.js @@ -27,6 +27,9 @@ export default class Form { const newPrice = isCurrencyDisabled ? price : price.slice(1); this._setState({ price: newPrice }); }; + onChangeTax = (tax) => { + this._setState({ tax: tax }); + }; setSoldByEach = () => { this._setState({ soldBy: "Each" }); }; diff --git a/src/stories/screens/InputItem/index.js b/src/stories/screens/InputItem/index.js index a4a5c77..2dab8c5 100644 --- a/src/stories/screens/InputItem/index.js +++ b/src/stories/screens/InputItem/index.js @@ -70,6 +70,7 @@ export default class InputItem extends React.Component { status: "item", name: "", price: "0.00", + tax: "0", sku: "", barcode: "", category: "No Category", @@ -219,6 +220,23 @@ export default class InputItem extends React.Component { + + + + + + this.frm.onChangeTax(value) + } + /> + + + diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index dd5c7ac..5a5c22f 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -292,6 +292,7 @@ class Settings extends React.Component { { name: strings.Company }, { name: strings.Sync }, ]; + if (this.props.attendant && this.props.attendant.role === "Owner") { menuItems = [ { name: strings.Bluetooth }, From fa816a138dfb5027ad456422710a700e8aef34d3 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Tue, 22 Oct 2019 13:48:41 +0800 Subject: [PATCH 02/29] Deletion of receiptline (Approve by manager feature) --- src/container/SalesContainer/index.js | 99 +++++---- src/container/SettingsContainer/index.js | 7 +- src/store/PosStore/AttendantStore.js | 37 ++-- src/store/StateStore/DefaultValues.js | 2 +- src/store/StateStore/Models.js | 2 +- src/store/StateStore/StateStore.js | 5 +- .../components/AttendantsFormComponent.js | 4 +- .../components/ConfirmationModalComponent.js | 203 +++++++++--------- .../components/ModalKeypadComponent.js | 6 +- src/stories/screens/InputItem/frm.js | 6 +- src/stories/screens/InputItem/index.js | 14 +- 11 files changed, 191 insertions(+), 194 deletions(-) diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index a11d7b4..53114ec 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -223,12 +223,12 @@ export default class SalesContainer extends React.Component { }; onDeleteReceiptLine = () => { - const { hideDeleteDialog } = this.props.stateStore; - hideDeleteDialog(); + const { hideDeleteDialog } = this.props.stateStore; + hideDeleteDialog(); - this.props.stateStore.changeConfirmation("AllReceiptLine"); - const { changeValue } = this.props.stateStore; - changeValue("confirmation", true, "Sales"); + this.props.stateStore.changeConfirmation("AllReceiptLine"); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); }; onBarcodeClick = () => { @@ -569,54 +569,53 @@ export default class SalesContainer extends React.Component { // remove the receipt store this.props.stateStore.changeValue("quantityModalVisible", false, "Sales"); }; - execute_method = (pin) => { - const { changeValue } = this.props.stateStore; - this.props.attendantStore.findAttendantBasedOnRole(pin) - .then(result => { - changeValue("confirmation", false, "Sales"); - if (result) { - if (this.props.stateStore.currentConfirmation === "ReceiptLine"){ - - this.onReceiptLineDelete(this.props.stateStore.index_value); - } - else if (this.props.stateStore.currentConfirmation === "AllReceiptLine"){ - const { hideDeleteDialog } = this.props.stateStore; - const { unselectReceiptLine, defaultReceipt } = this.props.receiptStore; - unselectReceiptLine(); - defaultReceipt.clear(); - hideDeleteDialog(); - } - showToast("Successfully Deleted Receiptline(s)"); - - } else { - showToastDanger("Approvers Pin Invalid"); - } - }); - } - confirmationModal(){ - const { changeValue } = this.props.stateStore; - return ( - this.execute_method(pin)} - onClose={() => changeValue("confirmation", false, "Sales")} - /> - ); - - } - showConfirmationModalReceiptLine = index => { - if (this.props.attendantStore.defaultAttendant.canApprove){ - this.onReceiptLineDelete(index); + execute_method = pin => { + const { changeValue } = this.props.stateStore; + this.props.attendantStore.findAttendantBasedOnRole(pin).then(result => { + changeValue("confirmation", false, "Sales"); + if (result) { + if (this.props.stateStore.currentConfirmation === "ReceiptLine") { + this.onReceiptLineDelete(this.props.stateStore.index_value); + } else if ( + this.props.stateStore.currentConfirmation === "AllReceiptLine" + ) { + const { hideDeleteDialog } = this.props.stateStore; + const { + unselectReceiptLine, + defaultReceipt, + } = this.props.receiptStore; + unselectReceiptLine(); + defaultReceipt.clear(); + hideDeleteDialog(); + } + showToast("Successfully Deleted Receiptline(s)"); } else { - this.props.stateStore.changeConfirmation("ReceiptLine"); - this.props.stateStore.changeIndex(index); - const { changeValue } = this.props.stateStore; - changeValue("confirmation", true, "Sales"); + showToastDanger("Approvers Pin Invalid"); } - + }); + }; + confirmationModal() { + const { changeValue } = this.props.stateStore; + return ( + this.execute_method(pin)} + onClose={() => changeValue("confirmation", false, "Sales")} + /> + ); + } + showConfirmationModalReceiptLine = index => { + if (this.props.attendantStore.defaultAttendant.canApprove) { + this.onReceiptLineDelete(index); + } else { + this.props.stateStore.changeConfirmation("ReceiptLine"); + this.props.stateStore.changeIndex(index); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); } - onReceiptLineDelete = (index) => { + }; + onReceiptLineDelete = index => { const { queueOrigin, currentTable } = this.props.stateStore; this.props.receiptStore.unselectReceiptLine(); diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index b17cddf..5779cd7 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -498,7 +498,6 @@ export default class SettingsContainer extends React.Component { }); } }); - } else if (values.status === "Edit Attendant") { const valueAttendant = await this.props.attendantStore.find( values.id, @@ -510,7 +509,7 @@ export default class SettingsContainer extends React.Component { pin_code: values.pin, role: values.role, canLogin: values.canLogin, - canApprove: values.canApprove, + canApprove: values.canApprove, commission: parseInt(values.commission, 10) > 0 ? parseInt(values.commission, 10) @@ -592,7 +591,7 @@ export default class SettingsContainer extends React.Component { pin_code: values.pin, role: values.role, canLogin: values.canLogin, - canApprove: values.canApprove, + canApprove: values.canApprove, commission: parseInt(values.commission, 10) > 0 ? parseInt(values.commission, 10) @@ -630,7 +629,7 @@ export default class SettingsContainer extends React.Component { pin_code: values.pin, role: values.role, canLogin: values.canLogin, - canApprove: values.canApprove, + canApprove: values.canApprove, commission: parseInt(values.commission, 10) > 0 ? parseInt(values.commission, 10) diff --git a/src/store/PosStore/AttendantStore.js b/src/store/PosStore/AttendantStore.js index 16efd3a..68b57f3 100644 --- a/src/store/PosStore/AttendantStore.js +++ b/src/store/PosStore/AttendantStore.js @@ -139,7 +139,7 @@ const AttendantStore = types pin_code: doc.pin_code, role: doc.role, canLogin: doc.canLogin ? doc.canLogin : false, - canApprove: doc.canApprove ? doc.canApprove : false, + canApprove: doc.canApprove ? doc.canApprove : false, commission: doc.commission, dateUpdated: doc.dateUpdated, syncStatus: doc.syncStatus, @@ -182,25 +182,24 @@ const AttendantStore = types }); }); }, - findAttendantBasedOnRole(pin) { - - return new Promise(function(resolve, reject) { - db - .find({ - selector: { - canApprove: { $regex: true }, - pin_code: { $regex: pin }, - }, - }) - .then(result => { - if (result.docs.length > 0) { - resolve(true); - } else { - resolve(false); - } - }); + findAttendantBasedOnRole(pin) { + return new Promise(function(resolve, reject) { + db + .find({ + selector: { + canApprove: { $regex: true }, + pin_code: { $regex: pin }, + }, + }) + .then(result => { + if (result.docs.length > 0) { + resolve(true); + } else { + resolve(false); + } }); - }, + }); + }, })); const Store = AttendantStore.create({}); diff --git a/src/store/StateStore/DefaultValues.js b/src/store/StateStore/DefaultValues.js index 080733f..c569417 100644 --- a/src/store/StateStore/DefaultValues.js +++ b/src/store/StateStore/DefaultValues.js @@ -22,7 +22,7 @@ export const sales = { fetching: false, addReceiptLineStatus: false, confirmOrder: false, - confirmation: false, + confirmation: false, commissionArray: JSON.stringify([]), }; export const listing = { diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index 14c81ca..21dc5a8 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -23,7 +23,7 @@ export const ModelSales = { discountSelectionStatus: types.optional(types.boolean, true), fetching: types.optional(types.boolean, false), confirmOrder: types.optional(types.boolean, false), - confirmation: types.optional(types.boolean, false), + confirmation: types.optional(types.boolean, false), addReceiptLineStatus: types.optional(types.boolean, false), }; export const ModelListing = { diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index 1b73709..9eed8cf 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -130,9 +130,10 @@ const StateStore = types setLoadingOrder(isLoadingOrder) { self.isLoadingOrder = isLoadingOrder; }, - changeConfirmation(currentConfirmation) { + changeConfirmation(currentConfirmation) { self.currentConfirmation = currentConfirmation; - },changeIndex(index) { + }, + changeIndex(index) { self.index_value = index; }, setOrders(orders) { diff --git a/src/stories/components/AttendantsFormComponent.js b/src/stories/components/AttendantsFormComponent.js index 01596d9..5249c62 100644 --- a/src/stories/components/AttendantsFormComponent.js +++ b/src/stories/components/AttendantsFormComponent.js @@ -20,7 +20,7 @@ class AddAttendantComponent extends React.Component { status: "Save Attendant", role: "Owner", canLogin: false, - canApprove: false, + canApprove: false, commission: "", }; } @@ -60,7 +60,7 @@ class AddAttendantComponent extends React.Component { securityPinStatus: true, securityConfirmPinStatus: true, canLogin: attendantInfo.canLogin, - canApprove: attendantInfo.canApprove, + canApprove: attendantInfo.canApprove, commission: attendantInfo.commission.toString(), }); } else { diff --git a/src/stories/components/ConfirmationModalComponent.js b/src/stories/components/ConfirmationModalComponent.js index b88f52a..954706d 100644 --- a/src/stories/components/ConfirmationModalComponent.js +++ b/src/stories/components/ConfirmationModalComponent.js @@ -9,118 +9,115 @@ import translation from "../.././translations/translation"; import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); export default class ConfirmationModalComponent extends React.Component { - constructor(props) { - super(props); - this.state = { - pin: "", - }; - } + constructor(props) { + super(props); + this.state = { + pin: "", + }; + } - onRequestClose = () => null; + onRequestClose = () => null; - onNumberPress = text => { + onNumberPress = text => { + this.setState({ pin: this.state.pin.concat(text) }); + }; - this.setState({ pin: this.state.pin.concat(text)}); - }; + onDeletePress = () => { + this.setState({ pin: this.state.pin.slice(0, -1) }); + }; - onDeletePress = () => { - this.setState({ pin: this.state.pin.slice(0, -1) }); - }; + onSubmit = () => { + const pin = parseFloat(this.state.pin); - onSubmit = () => { - const pin = parseFloat(this.state.pin); + this.setState({ pin: "" }); + this.props.onSubmit(pin); + }; - this.setState({ pin: "" }); - this.props.onSubmit(pin); - }; + render() { + strings.setLanguage(currentLanguage().companyLanguage); + return ( + + + + + Approvers Pin + this.props.onClose()} + > + + + - render() { - strings.setLanguage(currentLanguage().companyLanguage); - return ( - + + + + + + - - - - ); - } + Confirm + + + + + ); + } } const styles = StyleSheet.create({ - view: { - flex: 1, - alignItems: "center", - flexDirection: "column", - justifyContent: "center", - backgroundColor: "#00000090", - }, - innerView: { - width: 240, - backgroundColor: "white", - }, - headerView: { - padding: 10, - borderBottomWidth: 0.5, - borderBottomColor: "#eee", - flexDirection: "row", - justifyContent: "space-between", - }, - headerText: { - color: "gray", - fontWeight: "bold", - }, - close: { - alignSelf: "flex-end", - }, - item: { - backgroundColor: "#eee", - }, - input: { - paddingRight: 15, - fontWeight: "bold" - }, - setButton: { - borderRadius: 0, - }, + view: { + flex: 1, + alignItems: "center", + flexDirection: "column", + justifyContent: "center", + backgroundColor: "#00000090", + }, + innerView: { + width: 240, + backgroundColor: "white", + }, + headerView: { + padding: 10, + borderBottomWidth: 0.5, + borderBottomColor: "#eee", + flexDirection: "row", + justifyContent: "space-between", + }, + headerText: { + color: "gray", + fontWeight: "bold", + }, + close: { + alignSelf: "flex-end", + }, + item: { + backgroundColor: "#eee", + }, + input: { + paddingRight: 15, + fontWeight: "bold", + }, + setButton: { + borderRadius: 0, + }, }); - diff --git a/src/stories/components/ModalKeypadComponent.js b/src/stories/components/ModalKeypadComponent.js index 046988c..96bedbe 100644 --- a/src/stories/components/ModalKeypadComponent.js +++ b/src/stories/components/ModalKeypadComponent.js @@ -44,7 +44,11 @@ export default class ModalKeypadComponent extends React.PureComponent { - {"noPeriod" in this.props ? null} /> : ()} + {"noPeriod" in this.props ? ( + null} /> + ) : ( + + )} diff --git a/src/stories/screens/InputItem/frm.js b/src/stories/screens/InputItem/frm.js index 9552c10..d97d869 100644 --- a/src/stories/screens/InputItem/frm.js +++ b/src/stories/screens/InputItem/frm.js @@ -27,9 +27,9 @@ export default class Form { const newPrice = isCurrencyDisabled ? price : price.slice(1); this._setState({ price: newPrice }); }; - onChangeTax = (tax) => { - this._setState({ tax: tax }); - }; + onChangeTax = tax => { + this._setState({ tax: tax }); + }; setSoldByEach = () => { this._setState({ soldBy: "Each" }); }; diff --git a/src/stories/screens/InputItem/index.js b/src/stories/screens/InputItem/index.js index 2dab8c5..3afcd88 100644 --- a/src/stories/screens/InputItem/index.js +++ b/src/stories/screens/InputItem/index.js @@ -225,14 +225,12 @@ export default class InputItem extends React.Component { - this.frm.onChangeTax(value) - } + value={this.state.tax} + keyboardType="numeric" + placeholder={"Tax(%)"} + // onBlur={this.onBlur} + // onFocus={this.onFocus} + onChangeText={value => this.frm.onChangeTax(value)} /> From 86b858fd7dbe25dbb79c27fa351635f8fc94ca53 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Tue, 22 Oct 2019 17:05:06 +0800 Subject: [PATCH 03/29] Deletion of receiptline (Approve by manager feature) Applying Discount (Approve by manager feature) --- src/container/PaymentContainer/index.js | 1107 +++++++++-------- src/container/ReceiptInfoContainer/index.js | 59 +- src/container/SalesContainer/index.js | 140 ++- src/container/SettingsContainer/index.js | 10 + src/store/PosStore/PrinterStore.js | 8 +- src/store/StateStore/DefaultValues.js | 1 + src/store/StateStore/Models.js | 1 + src/store/StateStore/StateStore.js | 4 + src/stories/components/CompanyComponent.js | 8 + .../components/QuantityModalComponent.js | 9 +- src/stories/screens/Settings/index.js | 2 + 11 files changed, 711 insertions(+), 638 deletions(-) diff --git a/src/container/PaymentContainer/index.js b/src/container/PaymentContainer/index.js index c2bc236..e883289 100644 --- a/src/container/PaymentContainer/index.js +++ b/src/container/PaymentContainer/index.js @@ -372,503 +372,510 @@ export default class PaymentContainer extends React.Component { totalAmountDue, ); if (res) { - const writePromises = []; + let writePromises = []; - writePromises.push(BluetoothSerial.write(TinyPOS.init())); + for (let printedReceipts = 0; printedReceipts < parseInt(this.props.printerStore.companySettings[0].changeNoReceipts,10); printedReceipts += 1){ - // Header - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].name - ? this.props.printerStore.companySettings[0].name.toString() - : "Bai Web and Mobile Lab" - : "Bai Web and Mobile Lab" - }`, - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); + writePromises = []; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].header.toString() - : "" - }`, - { align: "center", size: "normal" }, - true, - ), - ), - ); + writePromises.push(BluetoothSerial.write(TinyPOS.init())); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); + // Header + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + this.props.printerStore.companySettings.length > 0 + ? this.props.printerStore.companySettings[0].name + ? this.props.printerStore.companySettings[0].name.toString() + : "" + : "" + }`, + {align: "center", size: "doubleheight"}, + true, + ), + ), + ); - // Date - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, - { size: "normal" }, - true, - ), - ), - ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + this.props.printerStore.companySettings.length > 0 + ? this.props.printerStore.companySettings[0].header.toString() + : "" + }`, + {align: "center", size: "normal"}, + true, + ), + ), + ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Cashier + - `${ - this.props.attendantStore.defaultAttendant.user_name - }`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.TransactionNo + `${finalReceiptNumber}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "Mode of payment: " + - this.props.stateStore.payment_state[0].selected, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Purchases, - { align: "center", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Items + - " " + - strings.Amount + - " ", - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + {size: "normal"}, + true, + ), + ), + ); - this.props.receiptStore.defaultReceipt.lines.map(val => { - let finalLines = ""; - - const name = val.item_name; - - if (name.length > 14) { - let quotientValue = name.length / 14; - for ( - let quotient = 0; - quotient < parseInt(quotientValue, 10); - quotient += 1 - ) { - let currentCounter = quotient * 14; - let nameCounter = ""; - for ( - let n = currentCounter; - n < (quotient + 1) * 14; - n += 1 - ) { - nameCounter = nameCounter + name[n]; - } - writePromises.push( - BluetoothSerial.write( + // Date + writePromises.push( + BluetoothSerial.write( TinyPOS.bufferedText( - `${nameCounter}`, - { align: "left", size: "normal" }, - true, + `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, + {size: "normal"}, + true, ), - ), - ); - } - if (name.length - parseInt(quotientValue, 10) * 14 > 0) { - let nameCounterOverflow = ""; - for ( - let m = parseInt(quotientValue, 10) * 14; - m < name.length; - m += 1 - ) { - nameCounterOverflow = nameCounterOverflow + name[m]; - } - writePromises.push( - BluetoothSerial.write( + ), + ); + + writePromises.push( + BluetoothSerial.write( TinyPOS.bufferedText( - `${nameCounterOverflow}`, - { align: "left", size: "normal" }, - true, + "================================", + {size: "normal"}, + true, ), - ), - ); - } - } else { - writePromises.push( + ), + ); + writePromises.push( BluetoothSerial.write( - TinyPOS.bufferedText( - `${name}`, - { align: "left", size: "normal" }, - true, - ), + TinyPOS.bufferedText( + strings.Cashier + + `${ + this.props.attendantStore.defaultAttendant.user_name + }`, + {align: "left", size: "normal"}, + true, + ), ), - ); - } + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.TransactionNo + `${finalReceiptNumber}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + {size: "normal"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "Mode of payment: " + + this.props.stateStore.payment_state[0].selected, + {align: "left", size: "normal"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + {size: "normal"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Purchases, + {align: "center", size: "normal"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Items + + " " + + strings.Amount + + " ", + {align: "left", size: "normal", weight: "bold"}, + true, + ), + ), + ); - let priceString = formatNumber( - parseFloat(val.price, 10), - ).toString(); - let qtyString = val.qty.toString(); - let amountString = formatNumber( - parseFloat(val.price, 10) * parseFloat(val.qty, 10), - ).toString(); + this.props.receiptStore.defaultReceipt.lines.map(val => { + let finalLines = ""; + + const name = val.item_name; + + if (name.length > 14) { + let quotientValue = name.length / 14; + for ( + let quotient = 0; + quotient < parseInt(quotientValue, 10); + quotient += 1 + ) { + let currentCounter = quotient * 14; + let nameCounter = ""; + for ( + let n = currentCounter; + n < (quotient + 1) * 14; + n += 1 + ) { + nameCounter = nameCounter + name[n]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounter}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + } + if (name.length - parseInt(quotientValue, 10) * 14 > 0) { + let nameCounterOverflow = ""; + for ( + let m = parseInt(quotientValue, 10) * 14; + m < name.length; + m += 1 + ) { + nameCounterOverflow = nameCounterOverflow + name[m]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounterOverflow}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + } + } else { + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${name}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + } - for (let ps = 0; ps < 12 - priceString.length; ps += 1) { - finalLines = finalLines + " "; - } + let priceString = formatNumber( + parseFloat(val.price, 10), + ).toString(); + let qtyString = val.qty.toString(); + let amountString = formatNumber( + parseFloat(val.price, 10) * parseFloat(val.qty, 10), + ).toString(); - finalLines = finalLines + priceString; + for (let ps = 0; ps < 12 - priceString.length; ps += 1) { + finalLines = finalLines + " "; + } - for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { - finalLines = finalLines + " "; - } - finalLines = finalLines + qtyString; + finalLines = finalLines + priceString; - for (let as = 0; as < 14 - amountString.length; as += 1) { - finalLines = finalLines + " "; - } + for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { + finalLines = finalLines + " "; + } + finalLines = finalLines + qtyString; + + for (let as = 0; as < 14 - amountString.length; as += 1) { + finalLines = finalLines + " "; + } + + finalLines = finalLines + amountString; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${finalLines}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + if (printedReceipts === 0){ - finalLines = finalLines + amountString; + totalPurchase = + parseFloat(totalPurchase, 10) + + parseFloat(val.price, 10) * parseFloat(val.qty, 10); + } + }); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${finalLines}`, - { align: "left", size: "normal" }, - true, + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + {align: "left", size: "normal", weight: "bold"}, + true, + ), ), - ), ); - totalPurchase = - parseFloat(totalPurchase, 10) + - parseFloat(val.price, 10) * parseFloat(val.qty, 10); - }); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - - let subTotal = strings.Subtotal; - let sub = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.subtotal, - 10, - ), - ).toString(); - for (let t = 0; t < 23 - sub.length; t += 1) { - subTotal = subTotal + " "; - } - subTotal = subTotal + sub; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${subTotal}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - let taxValue = strings.Tax; - let tax = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.get_tax_total, - 10, - ), - ).toString(); - for (let t = 0; t < 29 - tax.length; t += 1) { - taxValue = taxValue + " "; - } - taxValue = taxValue + tax; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${taxValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - let discountValue = strings.Discount; - let discount = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, - ), - ).toString(); - for (let d = 0; d < 24 - discount.length; d += 1) { - discountValue = discountValue + " "; - } - discountValue = discountValue + discount; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${discountValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - - let commissionValue = strings.Commission; - - let commission_total = formatNumber( - parseFloat(commission_toto, 10), - ).toString(); - for (let d = 0; d < 22 - commission_total.length; d += 1) { - commissionValue = commissionValue + " "; - } - commissionValue = commissionValue + commission_total; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${commissionValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - let total = ""; - total = total + strings.TotalAmount; - - for ( - let totalLength = 0; - totalLength < - 20 - - formatNumber(parseFloat(totalPurchase, 10)).toString() - .length; - totalLength += 1 - ) { - total = total + " "; - } - total = - total + - formatNumber( - parseFloat(totalPurchase, 10) - - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, - ) + + let subTotal = strings.Subtotal; + let sub = formatNumber( parseFloat( - this.props.receiptStore.defaultReceipt.get_tax_total, - 10, + this.props.receiptStore.defaultReceipt.subtotal, + 10, ), ).toString(); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${total}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - let cash = strings.Cash; - for ( - let cashLength = 0; - cashLength < - 28 - - formatNumber( - parseFloat(this.props.stateStore.payment_value, 10), - ).toString().length; - cashLength += 1 - ) { - cash = cash + " "; - } - cash = - cash + - formatNumber( - parseFloat(this.props.stateStore.payment_value, 10), + for (let t = 0; t < 23 - sub.length; t += 1) { + subTotal = subTotal + " "; + } + subTotal = subTotal + sub; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${subTotal}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + let taxValue = strings.Tax; + let tax = formatNumber( + parseFloat( + this.props.receiptStore.defaultReceipt.get_tax_total, + 10, + ), ).toString(); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${cash}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - let change = strings.Change; - let changeValue = formatNumber( - parseFloat( - parseFloat(this.props.stateStore.payment_value, 10) - - (parseFloat(totalPurchase, 10) - - parseFloat( + for (let t = 0; t < 29 - tax.length; t += 1) { + taxValue = taxValue + " "; + } + taxValue = taxValue + tax; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${taxValue}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + let discountValue = strings.Discount; + let discount = formatNumber( + parseFloat( this.props.receiptStore.defaultReceipt.discounts, 10, - ) + - parseFloat( - this.props.receiptStore.defaultReceipt - .get_tax_total, - 10, - )), - 10, - ), - ).toString(); - for ( - let changeLength = 0; - changeLength < 26 - changeValue.length; - changeLength += 1 - ) { - change = change + " "; - } - change = change + changeValue; + ), + ).toString(); + for (let d = 0; d < 24 - discount.length; d += 1) { + discountValue = discountValue + " "; + } + discountValue = discountValue + discount; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${discountValue}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${change}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.ThisServesAsYour, - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.OfficialReceipt + "\n", - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].footer.toString() - : "" - }`, - { align: "center", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "\n" + - strings.POSProvider + - "Bai Web and Mobile Lab\n" + - "Insular Life Bldg, Don Apolinar\n" + - "Velez cor. Oldarico Akut St.,\n" + - "Cagayan de Oro, 9000,\n" + - "Misamis Oriental\n" + - strings.AccredNo + - strings.DateIssued + - strings.ValidUntil, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.ThisReceiptShallBeValidFor + - strings.FiveYearsFromTheDateOf + - strings.ThePermitToUse, - { align: "center", size: "normal" }, - true, - ), - ), - ); + let commissionValue = strings.Commission; - // Add 3 new lines - writePromises.push( - BluetoothSerial.write(TinyPOS.bufferedLine(3)), - ); + let commission_total = formatNumber( + parseFloat(commission_toto, 10), + ).toString(); + for (let d = 0; d < 22 - commission_total.length; d += 1) { + commissionValue = commissionValue + " "; + } + commissionValue = commissionValue + commission_total; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${commissionValue}`, + {align: "left", size: "normal"}, + true, + ), + ), + ); + + let total = ""; + total = total + strings.TotalAmount; + + for ( + let totalLength = 0; + totalLength < + 20 - + formatNumber(parseFloat(totalPurchase, 10)).toString() + .length; + totalLength += 1 + ) { + total = total + " "; + } + total = + total + + formatNumber( + parseFloat(totalPurchase, 10) - + parseFloat( + this.props.receiptStore.defaultReceipt.discounts, + 10, + ) + + parseFloat( + this.props.receiptStore.defaultReceipt.get_tax_total, + 10, + ), + ).toString(); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${total}`, + {align: "left", size: "normal", weight: "bold"}, + true, + ), + ), + ); + let cash = strings.Cash; + for ( + let cashLength = 0; + cashLength < + 28 - + formatNumber( + parseFloat(this.props.stateStore.payment_value, 10), + ).toString().length; + cashLength += 1 + ) { + cash = cash + " "; + } + cash = + cash + + formatNumber( + parseFloat(this.props.stateStore.payment_value, 10), + ).toString(); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${cash}`, + {align: "left", size: "normal", weight: "bold"}, + true, + ), + ), + ); + let change = strings.Change; + let changeValue = formatNumber( + parseFloat( + parseFloat(this.props.stateStore.payment_value, 10) - + (parseFloat(totalPurchase, 10) - + parseFloat( + this.props.receiptStore.defaultReceipt.discounts, + 10, + ) + + parseFloat( + this.props.receiptStore.defaultReceipt + .get_tax_total, + 10, + )), + 10, + ), + ).toString(); + for ( + let changeLength = 0; + changeLength < 26 - changeValue.length; + changeLength += 1 + ) { + change = change + " "; + } + change = change + changeValue; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${change}`, + {align: "left", size: "normal", weight: "bold"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + {size: "normal"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.ThisServesAsYour, + {align: "center", size: "doubleheight"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.OfficialReceipt + "\n", + {align: "center", size: "doubleheight"}, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + this.props.printerStore.companySettings.length > 0 + ? this.props.printerStore.companySettings[0].footer.toString() + : "" + }`, + {align: "center", size: "normal"}, + true, + ), + ), + ); + // writePromises.push( + // BluetoothSerial.write( + // TinyPOS.bufferedText( + // "\n" + + // strings.POSProvider + + // "Bai Web and Mobile Lab\n" + + // "Insular Life Bldg, Don Apolinar\n" + + // "Velez cor. Oldarico Akut St.,\n" + + // "Cagayan de Oro, 9000,\n" + + // "Misamis Oriental\n" + + // strings.AccredNo + + // strings.DateIssued + + // strings.ValidUntil, + // { align: "left", size: "normal" }, + // true, + // ), + // ), + // ); + // writePromises.push( + // BluetoothSerial.write( + // TinyPOS.bufferedText( + // strings.ThisReceiptShallBeValidFor + + // strings.FiveYearsFromTheDateOf + + // strings.ThePermitToUse, + // { align: "center", size: "normal" }, + // true, + // ), + // ), + // ); + + // Add 3 new lines + writePromises.push( + BluetoothSerial.write(TinyPOS.bufferedLine(3)), + ); + } // Push drawer writePromises.push( BluetoothSerial.write(TinyPOS.kickCashDrawer()), @@ -876,86 +883,98 @@ export default class PaymentContainer extends React.Component { writePromises.push( BluetoothSerial.write(TinyPOS.kickCashDrawer()), ); + Promise.all(writePromises) + .then(res2 => { + receiptCurrent.completed( + this.props.attendantStore.defaultAttendant.user_name, + ); + + this.props.receiptStore.defaultReceipt.changeTaxesAmount( + this.props.receiptStore.defaultReceipt.get_tax_total, + ); + // add to row + + this.props.paymentStore.add({ + receipt: this.props.receiptStore.defaultReceipt._id.toString(), + date: Date.now(), + paid: parseInt(this.props.stateStore.payment_value, 10), + type: this.props.stateStore.payment_state[0].selected, + dateUpdated: Date.now(), + syncStatus: false, + }); + + + + // Reset payment amount + // this.setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + this.props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + this.props.stateStore.changeValue( + "paymentAmount", + 0, + "Payment", + ); + + Toast.show({ + text: strings.TransactionCompleted, + duration: 5000, + }); + + }) + .catch(err => { + receiptCurrent.completed( + this.props.attendantStore.defaultAttendant.user_name, + ); + + this.props.receiptStore.defaultReceipt.changeTaxesAmount( + this.props.receiptStore.defaultReceipt.get_tax_total, + ); + + // add to row + + + this.props.paymentStore.add({ + receipt: this.props.receiptStore.defaultReceipt._id.toString(), + date: Date.now(), + paid: parseInt(this.props.stateStore.payment_value, 10), + type: this.props.stateStore.payment_state[0].selected, + dateUpdated: Date.now(), + syncStatus: false, + }); + + // this.setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + this.props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + this.props.stateStore.changeValue( + "paymentAmount", + 0, + "Payment", + ); + + Toast.show({ + text: err.message + strings.TransactionCompleted, + buttonText: strings.Okay, + position: "bottom", + duration: 5000, + }); + + + + }); + - Promise.all(writePromises) - .then(res2 => { - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, - ); - // add to row - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - - // Reset payment amount - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - this.props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - this.props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - - Toast.show({ - text: strings.TransactionCompleted, - duration: 5000, - }); - }) - .catch(err => { - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, - ); - - // add to row - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - this.props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - this.props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - Toast.show({ - text: err.message + strings.TransactionCompleted, - buttonText: strings.Okay, - position: "bottom", - duration: 5000, - }); - }); } else { receiptCurrent.completed( this.props.attendantStore.defaultAttendant.user_name, diff --git a/src/container/ReceiptInfoContainer/index.js b/src/container/ReceiptInfoContainer/index.js index 10d57bf..ec09d54 100644 --- a/src/container/ReceiptInfoContainer/index.js +++ b/src/container/ReceiptInfoContainer/index.js @@ -476,36 +476,35 @@ export default class ReceiptInfoContainer extends React.Component { ), ), ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "\n" + - strings.POSProvider + - "Bai Web and Mobile Lab\n" + - "Insular Life Bldg, Don Apolinar\n" + - "Velez cor. Oldarico Akut St.,\n" + - "Cagayan de Oro, 9000,\n" + - "Misamis Oriental\n" + - strings.AccredNo + - strings.DateIssued + - strings.ValidUntil, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.ThisReceiptShallBeValidFor + - strings.FiveYearsFromTheDateOf + - strings.ThePermitToUse, - { align: "center", size: "normal" }, - true, - ), - ), - ); - + // writePromises.push( + // BluetoothSerial.write( + // TinyPOS.bufferedText( + // "\n" + + // strings.POSProvider + + // "Bai Web and Mobile Lab\n" + + // "Insular Life Bldg, Don Apolinar\n" + + // "Velez cor. Oldarico Akut St.,\n" + + // "Cagayan de Oro, 9000,\n" + + // "Misamis Oriental\n" + + // strings.AccredNo + + // strings.DateIssued + + // strings.ValidUntil, + // { align: "left", size: "normal" }, + // true, + // ), + // ), + // ); + // writePromises.push( + // BluetoothSerial.write( + // TinyPOS.bufferedText( + // strings.ThisReceiptShallBeValidFor + + // strings.FiveYearsFromTheDateOf + + // strings.ThePermitToUse, + // { align: "center", size: "normal" }, + // true, + // ), + // ), + // ); // Add 3 new lines writePromises.push(BluetoothSerial.write(TinyPOS.bufferedLine(3))); diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 53114ec..7cc4c28 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -240,6 +240,7 @@ export default class SalesContainer extends React.Component { }; onDiscountClick = () => { + const { changeValue } = this.props.stateStore; const { defaultReceipt } = this.props.receiptStore; @@ -314,32 +315,40 @@ export default class SalesContainer extends React.Component { changeValue("selectedDiscount", discount, "Sales"); changeValue("selectedDiscountIndex", index, "Sales"); } - onDiscountEdit = val => { - const { changeValue } = this.props.stateStore; - const { defaultReceipt } = this.props.receiptStore; - const { rows, setDiscount } = this.props.discountStore; - const { - discountSelectionStatus, - selectedDiscountIndex, - } = this.props.stateStore.sales_state[0]; - - if (discountSelectionStatus) { - defaultReceipt.addOnTheFlyReceiptDiscount({ - value: parseFloat(val.onTheFlyDiscountValue, 10), - percentageType: val.percentageType, - }); + if (this.props.attendantStore.defaultAttendant.canApprove) { + this.onDiscountApply(val); } else { - const discount = rows[selectedDiscountIndex]; - - setDiscount(discount); - defaultReceipt.addReceiptDiscount(discount); + this.props.stateStore.changeDiscountString(JSON.stringify(val)); + this.props.stateStore.changeConfirmation("AllDiscount"); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); } - - // hide modal - changeValue("discountSelection", false, "Sales"); }; + onDiscountApply = val => { + const { changeValue } = this.props.stateStore; + const { defaultReceipt } = this.props.receiptStore; + const { rows, setDiscount } = this.props.discountStore; + const { + discountSelectionStatus, + selectedDiscountIndex, + } = this.props.stateStore.sales_state[0]; + + if (discountSelectionStatus) { + defaultReceipt.addOnTheFlyReceiptDiscount({ + value: parseFloat(val.onTheFlyDiscountValue, 10), + percentageType: val.percentageType, + }); + } else { + const discount = rows[selectedDiscountIndex]; + setDiscount(discount); + defaultReceipt.addReceiptDiscount(discount); + } + + // hide modal + changeValue("discountSelection", false, "Sales"); + } confirmReceiptDeleteDialog() { const { hideDeleteDialog } = this.props.stateStore; const { deleteDialogVisible } = this.props.stateStore.sales_state[0]; @@ -527,55 +536,67 @@ export default class SalesContainer extends React.Component { /> ); } + onQuantitySubmit = quantity => { + if (this.props.attendantStore.defaultAttendant.canApprove || parseFloat(quantity.discount) === 0) { + this.setEditedFigures(quantity); + } else if (!this.props.attendantStore.defaultAttendant.canApprove && parseFloat(quantity.discount) > 0) { + this.props.stateStore.changeDiscountString(JSON.stringify(quantity)); + this.props.stateStore.changeConfirmation("SingleDiscount"); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); + } // line - this.setState({ onChangeStatues: false }); - const line = this.props.receiptStore.selectedLine; + }; + setEditedFigures = figures => { + this.setState({ onChangeStatues: false }); + const line = this.props.receiptStore.selectedLine; - const qty = parseFloat(quantity.quantity) - ? parseFloat(quantity.quantity) - : parseFloat(quantity.defaultQty); + const qty = parseFloat(figures.quantity) + ? parseFloat(figures.quantity) + : parseFloat(figures.defaultQty); - if (line.sold_by === "Each") { - if (isFloat(qty)) { - showToast(strings.QuantityIsNotAllowed, "warning"); + if (line.sold_by === "Each") { + if (isFloat(qty)) { + showToast(strings.QuantityIsNotAllowed, "warning"); + } else { + showToast(strings.ReceiptLineIsModified); + line.setQuantity(Number(qty.toFixed(2))); + } } else { - showToast(strings.ReceiptLineIsModified); - line.setQuantity(Number(qty.toFixed(2))); + showToast(strings.ReceiptLineIsModified); + line.setQuantity(Number(qty.toFixed(2))); } - } else { - showToast(strings.ReceiptLineIsModified); - line.setQuantity(Number(qty.toFixed(2))); - } - const price = parseFloat(quantity.price) - ? parseFloat(quantity.price) - : parseFloat(quantity.defaultPrice); + const price = parseFloat(figures.price) + ? parseFloat(figures.price) + : parseFloat(figures.defaultPrice); - // set the price - line.setPrice(Number(price.toFixed(2))); - line.setDiscountRate( - parseFloat(quantity.discount) > 0 ? parseFloat(quantity.discount) : 0, - quantity.percentageType, - ); + // set the price + line.setPrice(Number(price.toFixed(2))); + line.setDiscountRate( + parseFloat(figures.discount) > 0 ? parseFloat(figures.discount) : 0, + figures.percentageType, + ); - // unselect the line - line.setCommissionDetails( - this.props.stateStore.sales_state[0].commissionArray, - ); - this.props.receiptStore.unselectReceiptLine(); - this.props.stateStore.changeValue("commissionArray", "[]", "Sales"); + // unselect the line + line.setCommissionDetails( + this.props.stateStore.sales_state[0].commissionArray, + ); + this.props.receiptStore.unselectReceiptLine(); + this.props.stateStore.changeValue("commissionArray", "[]", "Sales"); - // remove the receipt store - this.props.stateStore.changeValue("quantityModalVisible", false, "Sales"); - }; + // remove the receipt store + this.props.stateStore.changeValue("quantityModalVisible", false, "Sales"); + } execute_method = pin => { const { changeValue } = this.props.stateStore; this.props.attendantStore.findAttendantBasedOnRole(pin).then(result => { - changeValue("confirmation", false, "Sales"); if (result) { + changeValue("confirmation", false, "Sales"); if (this.props.stateStore.currentConfirmation === "ReceiptLine") { this.onReceiptLineDelete(this.props.stateStore.index_value); + showToast("Successfully Deleted Receiptline(s)"); } else if ( this.props.stateStore.currentConfirmation === "AllReceiptLine" ) { @@ -587,13 +608,22 @@ export default class SalesContainer extends React.Component { unselectReceiptLine(); defaultReceipt.clear(); hideDeleteDialog(); + showToast("Successfully Deleted Receiptline(s)"); + } else if (this.props.stateStore.currentConfirmation === "AllDiscount"){ + this.onDiscountApply(JSON.parse(this.props.stateStore.discount_string)); + showToast("Successfully Applied Discount"); + } else if (this.props.stateStore.currentConfirmation === "SingleDiscount"){ + this.setEditedFigures(JSON.parse(this.props.stateStore.discount_string)); + showToast("Successfully Applied Discount"); } - showToast("Successfully Deleted Receiptline(s)"); + } else { showToastDanger("Approvers Pin Invalid"); } }); }; + + confirmationModal() { const { changeValue } = this.props.stateStore; return ( diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index 5779cd7..5a46bcd 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -98,6 +98,10 @@ export default class SettingsContainer extends React.Component { "tax", this.props.printerStore.companySettings[0].tax.toString(), "Settings", + ); this.props.stateStore.changeValue( + "changeNoReceipts", + this.props.printerStore.companySettings[0].changeNoReceipts.toString(), + "Settings", ); this.props.stateStore.changeValue( "companyHeader", @@ -369,6 +373,7 @@ export default class SettingsContainer extends React.Component { footer: this.props.stateStore.settings_state[0].companyFooter, countryCode: this.props.stateStore.settings_state[0].companyCountry, currencyDisable: this.props.stateStore.isCurrencyDisabled, + changeNoReceipts: this.props.stateStore.settings_state[0].changeNoReceipts, }); } else { this.props.printerStore.addCompany({ @@ -380,6 +385,8 @@ export default class SettingsContainer extends React.Component { footer: this.props.stateStore.settings_state[0].companyFooter, countryCode: this.props.stateStore.settings_state[0].companyCountry, currencyDisable: this.props.stateStore.isCurrencyDisabled, + changeNoReceipts: this.props.stateStore.settings_state[0].changeNoReceipts, + }); } @@ -855,6 +862,9 @@ export default class SettingsContainer extends React.Component { changeName={text => stateStore.changeValue("companyName", text, "Settings") } + changeNoReceipts={text => + stateStore.changeValue("changeNoReceipts", text, "Settings") + } changeTax={text => stateStore.changeValue("tax", text, "Settings")} changeCountry={text => this.onChangeCurrency(text)} changeHeader={text => diff --git a/src/store/PosStore/PrinterStore.js b/src/store/PosStore/PrinterStore.js index fec9bc0..fe59d94 100644 --- a/src/store/PosStore/PrinterStore.js +++ b/src/store/PosStore/PrinterStore.js @@ -72,6 +72,7 @@ export const Company = types name: types.string, header: types.string, footer: types.string, + changeNoReceipts: types.string, companyLanguage: types.string, tax: types.optional(types.string, "0"), countryCode: types.optional(types.string, "PHP"), @@ -332,12 +333,16 @@ const Store = types if (!entries.rows[i].doc.companyLanguage) { entries.rows[i].doc.companyLanguage = "en"; } + if (!entries.rows[i].doc.changeNoReceipts) { + entries.rows[i].doc.changeNoReceipts = "1"; + } self.addCompany(JSON.parse(JSON.stringify(entries.rows[i].doc))); } } if (entries.rows.length <= 0) { self.addCompany({ name: "", + changeNoReceipts: "1", header: "", footer: "", companyLanguage: "en", @@ -349,7 +354,8 @@ const Store = types } else { self.addCompany({ name: "", - header: "", + changeNoReceipts: "1", + header: "", companyLanguage: "en", footer: "", tax: "0", diff --git a/src/store/StateStore/DefaultValues.js b/src/store/StateStore/DefaultValues.js index c569417..ecebfe5 100644 --- a/src/store/StateStore/DefaultValues.js +++ b/src/store/StateStore/DefaultValues.js @@ -64,6 +64,7 @@ export const settings = { connectionStatus: "Not Connected", currentAddress: "", companyName: "", + changeNoReceipts: "1", tax: "0", companyHeader: "", companyFooter: "", diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index 21dc5a8..6da745a 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -65,6 +65,7 @@ export const ModelSettings = { connectionStatus: types.optional(types.string, "Not Connected"), currentAddress: types.optional(types.string, ""), companyName: types.optional(types.string, ""), + changeNoReceipts: types.optional(types.string, ""), tax: types.optional(types.string, "0"), companyHeader: types.optional(types.string, ""), companyFooter: types.optional(types.string, ""), diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index 9eed8cf..8ecffdf 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -34,6 +34,7 @@ const StateStore = types isLoadingOrder: types.optional(types.boolean, false), currentConfirmation: types.optional(types.string, ""), index_value: types.optional(types.number, 0), + discount_string: types.optional(types.string, "{}"), // Settings queueHost: types.optional(types.string, ""), hasTailOrder: types.optional(types.boolean, false), @@ -147,6 +148,9 @@ const StateStore = types }, setQueueHost(host) { self.queueHost = host; + }, + changeDiscountString(discount) { + self.discount_string = discount; }, toggleTailOrder() { self.hasTailOrder = !self.hasTailOrder; diff --git a/src/stories/components/CompanyComponent.js b/src/stories/components/CompanyComponent.js index a7696cc..dac7400 100644 --- a/src/stories/components/CompanyComponent.js +++ b/src/stories/components/CompanyComponent.js @@ -123,6 +123,13 @@ class CompanyComponent extends React.PureComponent { + + {strings.CompanyHeader} diff --git a/src/stories/components/QuantityModalComponent.js b/src/stories/components/QuantityModalComponent.js index 618d565..02edf3c 100644 --- a/src/stories/components/QuantityModalComponent.js +++ b/src/stories/components/QuantityModalComponent.js @@ -471,14 +471,7 @@ export default class QuantityModalComponent extends React.Component { }} > - {strings.Set}{" "} - {this.state.status === "Qty" - ? "quantity" - : this.state.status === "Price" - ? "price" - : this.state.status === "Commission" - ? "commission" - : ""} + Edit Transaction diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index 5a5c22f..c9580e9 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -163,6 +163,7 @@ class Settings extends React.Component { editStatus, toggleCurrencyDisabled, isCurrencyDisabled, + changeNoReceipts } = this.props; if (this.props.returnValue === strings.Bluetooth) { @@ -199,6 +200,7 @@ class Settings extends React.Component { Date: Tue, 22 Oct 2019 17:05:41 +0800 Subject: [PATCH 04/29] Deletion of receiptline (Approve by manager feature) Applying Discount (Approve by manager feature) --- src/container/PaymentContainer/index.js | 835 +++++++++--------- src/container/SalesContainer/index.js | 163 ++-- src/container/SettingsContainer/index.js | 10 +- src/store/PosStore/PrinterStore.js | 8 +- src/store/StateStore/DefaultValues.js | 2 +- src/store/StateStore/Models.js | 2 +- src/store/StateStore/StateStore.js | 2 +- src/stories/components/CompanyComponent.js | 2 +- .../components/QuantityModalComponent.js | 4 +- src/stories/screens/Settings/index.js | 2 +- 10 files changed, 522 insertions(+), 508 deletions(-) diff --git a/src/container/PaymentContainer/index.js b/src/container/PaymentContainer/index.js index e883289..332c58a 100644 --- a/src/container/PaymentContainer/index.js +++ b/src/container/PaymentContainer/index.js @@ -372,474 +372,486 @@ export default class PaymentContainer extends React.Component { totalAmountDue, ); if (res) { - let writePromises = []; - - for (let printedReceipts = 0; printedReceipts < parseInt(this.props.printerStore.companySettings[0].changeNoReceipts,10); printedReceipts += 1){ - - writePromises = []; + let writePromises = []; + + for ( + let printedReceipts = 0; + printedReceipts < + parseInt( + this.props.printerStore.companySettings[0] + .changeNoReceipts, + 10, + ); + printedReceipts += 1 + ) { + writePromises = []; writePromises.push(BluetoothSerial.write(TinyPOS.init())); // Header writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].name - ? this.props.printerStore.companySettings[0].name.toString() - : "" - : "" - }`, - {align: "center", size: "doubleheight"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + this.props.printerStore.companySettings.length > 0 + ? this.props.printerStore.companySettings[0].name + ? this.props.printerStore.companySettings[0].name.toString() + : "" + : "" + }`, + { align: "center", size: "doubleheight" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].header.toString() - : "" - }`, - {align: "center", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + this.props.printerStore.companySettings.length > 0 + ? this.props.printerStore.companySettings[0].header.toString() + : "" + }`, + { align: "center", size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - {size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, ), + ), ); // Date writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, - {size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, + { size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - {size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Cashier + - `${ - this.props.attendantStore.defaultAttendant.user_name - }`, - {align: "left", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Cashier + + `${ + this.props.attendantStore.defaultAttendant + .user_name + }`, + { align: "left", size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.TransactionNo + `${finalReceiptNumber}`, - {align: "left", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.TransactionNo + `${finalReceiptNumber}`, + { align: "left", size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - {size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "Mode of payment: " + - this.props.stateStore.payment_state[0].selected, - {align: "left", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + "Mode of payment: " + + this.props.stateStore.payment_state[0].selected, + { align: "left", size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - {size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Purchases, - {align: "center", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Purchases, + { align: "center", size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Items + - " " + - strings.Amount + - " ", - {align: "left", size: "normal", weight: "bold"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Items + + " " + + strings.Amount + + " ", + { align: "left", size: "normal", weight: "bold" }, + true, ), + ), ); this.props.receiptStore.defaultReceipt.lines.map(val => { - let finalLines = ""; - - const name = val.item_name; - - if (name.length > 14) { - let quotientValue = name.length / 14; - for ( - let quotient = 0; - quotient < parseInt(quotientValue, 10); - quotient += 1 - ) { - let currentCounter = quotient * 14; - let nameCounter = ""; - for ( - let n = currentCounter; - n < (quotient + 1) * 14; - n += 1 - ) { - nameCounter = nameCounter + name[n]; - } - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${nameCounter}`, - {align: "left", size: "normal"}, - true, - ), - ), - ); - } - if (name.length - parseInt(quotientValue, 10) * 14 > 0) { - let nameCounterOverflow = ""; - for ( - let m = parseInt(quotientValue, 10) * 14; - m < name.length; - m += 1 - ) { - nameCounterOverflow = nameCounterOverflow + name[m]; - } - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${nameCounterOverflow}`, - {align: "left", size: "normal"}, - true, - ), - ), - ); - } - } else { - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${name}`, - {align: "left", size: "normal"}, - true, - ), - ), - ); + let finalLines = ""; + + const name = val.item_name; + + if (name.length > 14) { + let quotientValue = name.length / 14; + for ( + let quotient = 0; + quotient < parseInt(quotientValue, 10); + quotient += 1 + ) { + let currentCounter = quotient * 14; + let nameCounter = ""; + for ( + let n = currentCounter; + n < (quotient + 1) * 14; + n += 1 + ) { + nameCounter = nameCounter + name[n]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounter}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); } - - let priceString = formatNumber( - parseFloat(val.price, 10), - ).toString(); - let qtyString = val.qty.toString(); - let amountString = formatNumber( - parseFloat(val.price, 10) * parseFloat(val.qty, 10), - ).toString(); - - for (let ps = 0; ps < 12 - priceString.length; ps += 1) { - finalLines = finalLines + " "; + if ( + name.length - parseInt(quotientValue, 10) * 14 > + 0 + ) { + let nameCounterOverflow = ""; + for ( + let m = parseInt(quotientValue, 10) * 14; + m < name.length; + m += 1 + ) { + nameCounterOverflow = nameCounterOverflow + name[m]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounterOverflow}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); } + } else { + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${name}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + } - finalLines = finalLines + priceString; + let priceString = formatNumber( + parseFloat(val.price, 10), + ).toString(); + let qtyString = val.qty.toString(); + let amountString = formatNumber( + parseFloat(val.price, 10) * parseFloat(val.qty, 10), + ).toString(); - for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { - finalLines = finalLines + " "; - } - finalLines = finalLines + qtyString; + for (let ps = 0; ps < 12 - priceString.length; ps += 1) { + finalLines = finalLines + " "; + } - for (let as = 0; as < 14 - amountString.length; as += 1) { - finalLines = finalLines + " "; - } + finalLines = finalLines + priceString; - finalLines = finalLines + amountString; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${finalLines}`, - {align: "left", size: "normal"}, - true, - ), - ), - ); - if (printedReceipts === 0){ + for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { + finalLines = finalLines + " "; + } + finalLines = finalLines + qtyString; - totalPurchase = - parseFloat(totalPurchase, 10) + - parseFloat(val.price, 10) * parseFloat(val.qty, 10); - } + for (let as = 0; as < 14 - amountString.length; as += 1) { + finalLines = finalLines + " "; + } + + finalLines = finalLines + amountString; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${finalLines}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + if (printedReceipts === 0) { + totalPurchase = + parseFloat(totalPurchase, 10) + + parseFloat(val.price, 10) * parseFloat(val.qty, 10); + } }); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - {align: "left", size: "normal", weight: "bold"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { align: "left", size: "normal", weight: "bold" }, + true, ), + ), ); let subTotal = strings.Subtotal; let sub = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.subtotal, - 10, - ), + parseFloat( + this.props.receiptStore.defaultReceipt.subtotal, + 10, + ), ).toString(); for (let t = 0; t < 23 - sub.length; t += 1) { - subTotal = subTotal + " "; + subTotal = subTotal + " "; } subTotal = subTotal + sub; writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${subTotal}`, - {align: "left", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${subTotal}`, + { align: "left", size: "normal" }, + true, ), + ), ); let taxValue = strings.Tax; let tax = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.get_tax_total, - 10, - ), + parseFloat( + this.props.receiptStore.defaultReceipt.get_tax_total, + 10, + ), ).toString(); for (let t = 0; t < 29 - tax.length; t += 1) { - taxValue = taxValue + " "; + taxValue = taxValue + " "; } taxValue = taxValue + tax; writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${taxValue}`, - {align: "left", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${taxValue}`, + { align: "left", size: "normal" }, + true, ), + ), ); let discountValue = strings.Discount; let discount = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, - ), + parseFloat( + this.props.receiptStore.defaultReceipt.discounts, + 10, + ), ).toString(); for (let d = 0; d < 24 - discount.length; d += 1) { - discountValue = discountValue + " "; + discountValue = discountValue + " "; } discountValue = discountValue + discount; writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${discountValue}`, - {align: "left", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${discountValue}`, + { align: "left", size: "normal" }, + true, ), + ), ); let commissionValue = strings.Commission; let commission_total = formatNumber( - parseFloat(commission_toto, 10), + parseFloat(commission_toto, 10), ).toString(); for (let d = 0; d < 22 - commission_total.length; d += 1) { - commissionValue = commissionValue + " "; + commissionValue = commissionValue + " "; } commissionValue = commissionValue + commission_total; writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${commissionValue}`, - {align: "left", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${commissionValue}`, + { align: "left", size: "normal" }, + true, ), + ), ); let total = ""; total = total + strings.TotalAmount; for ( - let totalLength = 0; - totalLength < - 20 - + let totalLength = 0; + totalLength < + 20 - formatNumber(parseFloat(totalPurchase, 10)).toString() - .length; - totalLength += 1 + .length; + totalLength += 1 ) { - total = total + " "; + total = total + " "; } total = - total + - formatNumber( - parseFloat(totalPurchase, 10) - - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, - ) + - parseFloat( - this.props.receiptStore.defaultReceipt.get_tax_total, - 10, - ), - ).toString(); + total + + formatNumber( + parseFloat(totalPurchase, 10) - + parseFloat( + this.props.receiptStore.defaultReceipt.discounts, + 10, + ) + + parseFloat( + this.props.receiptStore.defaultReceipt + .get_tax_total, + 10, + ), + ).toString(); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${total}`, - {align: "left", size: "normal", weight: "bold"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${total}`, + { align: "left", size: "normal", weight: "bold" }, + true, ), + ), ); let cash = strings.Cash; for ( - let cashLength = 0; - cashLength < - 28 - + let cashLength = 0; + cashLength < + 28 - formatNumber( - parseFloat(this.props.stateStore.payment_value, 10), + parseFloat(this.props.stateStore.payment_value, 10), ).toString().length; - cashLength += 1 + cashLength += 1 ) { - cash = cash + " "; + cash = cash + " "; } cash = - cash + - formatNumber( - parseFloat(this.props.stateStore.payment_value, 10), - ).toString(); + cash + + formatNumber( + parseFloat(this.props.stateStore.payment_value, 10), + ).toString(); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${cash}`, - {align: "left", size: "normal", weight: "bold"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${cash}`, + { align: "left", size: "normal", weight: "bold" }, + true, ), + ), ); let change = strings.Change; let changeValue = formatNumber( - parseFloat( - parseFloat(this.props.stateStore.payment_value, 10) - - (parseFloat(totalPurchase, 10) - + parseFloat( + parseFloat(this.props.stateStore.payment_value, 10) - + (parseFloat(totalPurchase, 10) - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, + this.props.receiptStore.defaultReceipt.discounts, + 10, ) + parseFloat( - this.props.receiptStore.defaultReceipt - .get_tax_total, - 10, + this.props.receiptStore.defaultReceipt + .get_tax_total, + 10, )), - 10, - ), + 10, + ), ).toString(); for ( - let changeLength = 0; - changeLength < 26 - changeValue.length; - changeLength += 1 + let changeLength = 0; + changeLength < 26 - changeValue.length; + changeLength += 1 ) { - change = change + " "; + change = change + " "; } change = change + changeValue; writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${change}`, - {align: "left", size: "normal", weight: "bold"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${change}`, + { align: "left", size: "normal", weight: "bold" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - {size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.ThisServesAsYour, - {align: "center", size: "doubleheight"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.ThisServesAsYour, + { align: "center", size: "doubleheight" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.OfficialReceipt + "\n", - {align: "center", size: "doubleheight"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.OfficialReceipt + "\n", + { align: "center", size: "doubleheight" }, + true, ), + ), ); writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].footer.toString() - : "" - }`, - {align: "center", size: "normal"}, - true, - ), + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + this.props.printerStore.companySettings.length > 0 + ? this.props.printerStore.companySettings[0].footer.toString() + : "" + }`, + { align: "center", size: "normal" }, + true, ), + ), ); // writePromises.push( // BluetoothSerial.write( @@ -873,9 +885,9 @@ export default class PaymentContainer extends React.Component { // Add 3 new lines writePromises.push( - BluetoothSerial.write(TinyPOS.bufferedLine(3)), + BluetoothSerial.write(TinyPOS.bufferedLine(3)), ); - } + } // Push drawer writePromises.push( BluetoothSerial.write(TinyPOS.kickCashDrawer()), @@ -883,98 +895,89 @@ export default class PaymentContainer extends React.Component { writePromises.push( BluetoothSerial.write(TinyPOS.kickCashDrawer()), ); - Promise.all(writePromises) - .then(res2 => { - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, - ); - // add to row - - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - - - - // Reset payment amount - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - this.props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - this.props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - - Toast.show({ - text: strings.TransactionCompleted, - duration: 5000, - }); - - }) - .catch(err => { - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, - ); - - // add to row - - - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - this.props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - this.props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - - Toast.show({ - text: err.message + strings.TransactionCompleted, - buttonText: strings.Okay, - position: "bottom", - duration: 5000, - }); - - - - }); - - + Promise.all(writePromises) + .then(res2 => { + receiptCurrent.completed( + this.props.attendantStore.defaultAttendant.user_name, + ); + + this.props.receiptStore.defaultReceipt.changeTaxesAmount( + this.props.receiptStore.defaultReceipt.get_tax_total, + ); + // add to row + + this.props.paymentStore.add({ + receipt: this.props.receiptStore.defaultReceipt._id.toString(), + date: Date.now(), + paid: parseInt(this.props.stateStore.payment_value, 10), + type: this.props.stateStore.payment_state[0].selected, + dateUpdated: Date.now(), + syncStatus: false, + }); + + // Reset payment amount + // this.setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + this.props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + this.props.stateStore.changeValue( + "paymentAmount", + 0, + "Payment", + ); + + Toast.show({ + text: strings.TransactionCompleted, + duration: 5000, + }); + }) + .catch(err => { + receiptCurrent.completed( + this.props.attendantStore.defaultAttendant.user_name, + ); + + this.props.receiptStore.defaultReceipt.changeTaxesAmount( + this.props.receiptStore.defaultReceipt.get_tax_total, + ); + + // add to row + + this.props.paymentStore.add({ + receipt: this.props.receiptStore.defaultReceipt._id.toString(), + date: Date.now(), + paid: parseInt(this.props.stateStore.payment_value, 10), + type: this.props.stateStore.payment_state[0].selected, + dateUpdated: Date.now(), + syncStatus: false, + }); + + // this.setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + this.props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + this.props.stateStore.changeValue( + "paymentAmount", + 0, + "Payment", + ); + + Toast.show({ + text: err.message + strings.TransactionCompleted, + buttonText: strings.Okay, + position: "bottom", + duration: 5000, + }); + }); } else { receiptCurrent.completed( this.props.attendantStore.defaultAttendant.user_name, diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 7cc4c28..2f3e2d4 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -240,7 +240,6 @@ export default class SalesContainer extends React.Component { }; onDiscountClick = () => { - const { changeValue } = this.props.stateStore; const { defaultReceipt } = this.props.receiptStore; @@ -319,36 +318,36 @@ export default class SalesContainer extends React.Component { if (this.props.attendantStore.defaultAttendant.canApprove) { this.onDiscountApply(val); } else { - this.props.stateStore.changeDiscountString(JSON.stringify(val)); - this.props.stateStore.changeConfirmation("AllDiscount"); - const { changeValue } = this.props.stateStore; - changeValue("confirmation", true, "Sales"); + this.props.stateStore.changeDiscountString(JSON.stringify(val)); + this.props.stateStore.changeConfirmation("AllDiscount"); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); } }; onDiscountApply = val => { - const { changeValue } = this.props.stateStore; - const { defaultReceipt } = this.props.receiptStore; - const { rows, setDiscount } = this.props.discountStore; - const { - discountSelectionStatus, - selectedDiscountIndex, - } = this.props.stateStore.sales_state[0]; - - if (discountSelectionStatus) { - defaultReceipt.addOnTheFlyReceiptDiscount({ - value: parseFloat(val.onTheFlyDiscountValue, 10), - percentageType: val.percentageType, - }); - } else { - const discount = rows[selectedDiscountIndex]; + const { changeValue } = this.props.stateStore; + const { defaultReceipt } = this.props.receiptStore; + const { rows, setDiscount } = this.props.discountStore; + const { + discountSelectionStatus, + selectedDiscountIndex, + } = this.props.stateStore.sales_state[0]; - setDiscount(discount); - defaultReceipt.addReceiptDiscount(discount); - } + if (discountSelectionStatus) { + defaultReceipt.addOnTheFlyReceiptDiscount({ + value: parseFloat(val.onTheFlyDiscountValue, 10), + percentageType: val.percentageType, + }); + } else { + const discount = rows[selectedDiscountIndex]; - // hide modal - changeValue("discountSelection", false, "Sales"); - } + setDiscount(discount); + defaultReceipt.addReceiptDiscount(discount); + } + + // hide modal + changeValue("discountSelection", false, "Sales"); + }; confirmReceiptDeleteDialog() { const { hideDeleteDialog } = this.props.stateStore; const { deleteDialogVisible } = this.props.stateStore.sales_state[0]; @@ -538,57 +537,63 @@ export default class SalesContainer extends React.Component { } onQuantitySubmit = quantity => { - if (this.props.attendantStore.defaultAttendant.canApprove || parseFloat(quantity.discount) === 0) { - this.setEditedFigures(quantity); - } else if (!this.props.attendantStore.defaultAttendant.canApprove && parseFloat(quantity.discount) > 0) { - this.props.stateStore.changeDiscountString(JSON.stringify(quantity)); - this.props.stateStore.changeConfirmation("SingleDiscount"); - const { changeValue } = this.props.stateStore; - changeValue("confirmation", true, "Sales"); - } + if ( + this.props.attendantStore.defaultAttendant.canApprove || + parseFloat(quantity.discount) === 0 + ) { + this.setEditedFigures(quantity); + } else if ( + !this.props.attendantStore.defaultAttendant.canApprove && + parseFloat(quantity.discount) > 0 + ) { + this.props.stateStore.changeDiscountString(JSON.stringify(quantity)); + this.props.stateStore.changeConfirmation("SingleDiscount"); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); + } // line }; setEditedFigures = figures => { - this.setState({ onChangeStatues: false }); - const line = this.props.receiptStore.selectedLine; + this.setState({ onChangeStatues: false }); + const line = this.props.receiptStore.selectedLine; - const qty = parseFloat(figures.quantity) - ? parseFloat(figures.quantity) - : parseFloat(figures.defaultQty); + const qty = parseFloat(figures.quantity) + ? parseFloat(figures.quantity) + : parseFloat(figures.defaultQty); - if (line.sold_by === "Each") { - if (isFloat(qty)) { - showToast(strings.QuantityIsNotAllowed, "warning"); - } else { - showToast(strings.ReceiptLineIsModified); - line.setQuantity(Number(qty.toFixed(2))); - } + if (line.sold_by === "Each") { + if (isFloat(qty)) { + showToast(strings.QuantityIsNotAllowed, "warning"); } else { - showToast(strings.ReceiptLineIsModified); - line.setQuantity(Number(qty.toFixed(2))); + showToast(strings.ReceiptLineIsModified); + line.setQuantity(Number(qty.toFixed(2))); } + } else { + showToast(strings.ReceiptLineIsModified); + line.setQuantity(Number(qty.toFixed(2))); + } - const price = parseFloat(figures.price) - ? parseFloat(figures.price) - : parseFloat(figures.defaultPrice); + const price = parseFloat(figures.price) + ? parseFloat(figures.price) + : parseFloat(figures.defaultPrice); - // set the price - line.setPrice(Number(price.toFixed(2))); - line.setDiscountRate( - parseFloat(figures.discount) > 0 ? parseFloat(figures.discount) : 0, - figures.percentageType, - ); + // set the price + line.setPrice(Number(price.toFixed(2))); + line.setDiscountRate( + parseFloat(figures.discount) > 0 ? parseFloat(figures.discount) : 0, + figures.percentageType, + ); - // unselect the line - line.setCommissionDetails( - this.props.stateStore.sales_state[0].commissionArray, - ); - this.props.receiptStore.unselectReceiptLine(); - this.props.stateStore.changeValue("commissionArray", "[]", "Sales"); + // unselect the line + line.setCommissionDetails( + this.props.stateStore.sales_state[0].commissionArray, + ); + this.props.receiptStore.unselectReceiptLine(); + this.props.stateStore.changeValue("commissionArray", "[]", "Sales"); - // remove the receipt store - this.props.stateStore.changeValue("quantityModalVisible", false, "Sales"); - } + // remove the receipt store + this.props.stateStore.changeValue("quantityModalVisible", false, "Sales"); + }; execute_method = pin => { const { changeValue } = this.props.stateStore; this.props.attendantStore.findAttendantBasedOnRole(pin).then(result => { @@ -596,7 +601,7 @@ export default class SalesContainer extends React.Component { changeValue("confirmation", false, "Sales"); if (this.props.stateStore.currentConfirmation === "ReceiptLine") { this.onReceiptLineDelete(this.props.stateStore.index_value); - showToast("Successfully Deleted Receiptline(s)"); + showToast("Successfully Deleted Receiptline(s)"); } else if ( this.props.stateStore.currentConfirmation === "AllReceiptLine" ) { @@ -608,22 +613,28 @@ export default class SalesContainer extends React.Component { unselectReceiptLine(); defaultReceipt.clear(); hideDeleteDialog(); - showToast("Successfully Deleted Receiptline(s)"); - } else if (this.props.stateStore.currentConfirmation === "AllDiscount"){ - this.onDiscountApply(JSON.parse(this.props.stateStore.discount_string)); - showToast("Successfully Applied Discount"); - } else if (this.props.stateStore.currentConfirmation === "SingleDiscount"){ - this.setEditedFigures(JSON.parse(this.props.stateStore.discount_string)); - showToast("Successfully Applied Discount"); + showToast("Successfully Deleted Receiptline(s)"); + } else if ( + this.props.stateStore.currentConfirmation === "AllDiscount" + ) { + this.onDiscountApply( + JSON.parse(this.props.stateStore.discount_string), + ); + showToast("Successfully Applied Discount"); + } else if ( + this.props.stateStore.currentConfirmation === "SingleDiscount" + ) { + this.setEditedFigures( + JSON.parse(this.props.stateStore.discount_string), + ); + showToast("Successfully Applied Discount"); } - } else { showToastDanger("Approvers Pin Invalid"); } }); }; - confirmationModal() { const { changeValue } = this.props.stateStore; return ( diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index 5a46bcd..e236455 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -98,7 +98,8 @@ export default class SettingsContainer extends React.Component { "tax", this.props.printerStore.companySettings[0].tax.toString(), "Settings", - ); this.props.stateStore.changeValue( + ); + this.props.stateStore.changeValue( "changeNoReceipts", this.props.printerStore.companySettings[0].changeNoReceipts.toString(), "Settings", @@ -373,7 +374,8 @@ export default class SettingsContainer extends React.Component { footer: this.props.stateStore.settings_state[0].companyFooter, countryCode: this.props.stateStore.settings_state[0].companyCountry, currencyDisable: this.props.stateStore.isCurrencyDisabled, - changeNoReceipts: this.props.stateStore.settings_state[0].changeNoReceipts, + changeNoReceipts: this.props.stateStore.settings_state[0] + .changeNoReceipts, }); } else { this.props.printerStore.addCompany({ @@ -385,8 +387,8 @@ export default class SettingsContainer extends React.Component { footer: this.props.stateStore.settings_state[0].companyFooter, countryCode: this.props.stateStore.settings_state[0].companyCountry, currencyDisable: this.props.stateStore.isCurrencyDisabled, - changeNoReceipts: this.props.stateStore.settings_state[0].changeNoReceipts, - + changeNoReceipts: this.props.stateStore.settings_state[0] + .changeNoReceipts, }); } diff --git a/src/store/PosStore/PrinterStore.js b/src/store/PosStore/PrinterStore.js index fe59d94..f06906c 100644 --- a/src/store/PosStore/PrinterStore.js +++ b/src/store/PosStore/PrinterStore.js @@ -72,7 +72,7 @@ export const Company = types name: types.string, header: types.string, footer: types.string, - changeNoReceipts: types.string, + changeNoReceipts: types.string, companyLanguage: types.string, tax: types.optional(types.string, "0"), countryCode: types.optional(types.string, "PHP"), @@ -342,7 +342,7 @@ const Store = types if (entries.rows.length <= 0) { self.addCompany({ name: "", - changeNoReceipts: "1", + changeNoReceipts: "1", header: "", footer: "", companyLanguage: "en", @@ -354,8 +354,8 @@ const Store = types } else { self.addCompany({ name: "", - changeNoReceipts: "1", - header: "", + changeNoReceipts: "1", + header: "", companyLanguage: "en", footer: "", tax: "0", diff --git a/src/store/StateStore/DefaultValues.js b/src/store/StateStore/DefaultValues.js index ecebfe5..c07bb85 100644 --- a/src/store/StateStore/DefaultValues.js +++ b/src/store/StateStore/DefaultValues.js @@ -64,7 +64,7 @@ export const settings = { connectionStatus: "Not Connected", currentAddress: "", companyName: "", - changeNoReceipts: "1", + changeNoReceipts: "1", tax: "0", companyHeader: "", companyFooter: "", diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index 6da745a..d71cab4 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -65,7 +65,7 @@ export const ModelSettings = { connectionStatus: types.optional(types.string, "Not Connected"), currentAddress: types.optional(types.string, ""), companyName: types.optional(types.string, ""), - changeNoReceipts: types.optional(types.string, ""), + changeNoReceipts: types.optional(types.string, ""), tax: types.optional(types.string, "0"), companyHeader: types.optional(types.string, ""), companyFooter: types.optional(types.string, ""), diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index 8ecffdf..dea1b18 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -149,7 +149,7 @@ const StateStore = types setQueueHost(host) { self.queueHost = host; }, - changeDiscountString(discount) { + changeDiscountString(discount) { self.discount_string = discount; }, toggleTailOrder() { diff --git a/src/stories/components/CompanyComponent.js b/src/stories/components/CompanyComponent.js index dac7400..8559dca 100644 --- a/src/stories/components/CompanyComponent.js +++ b/src/stories/components/CompanyComponent.js @@ -129,7 +129,7 @@ class CompanyComponent extends React.PureComponent { onChange={this.props.changeNoReceipts} value={this.props.values.changeNoReceipts} label="Printed Receipts per Transaction" - /> + /> - - Edit Transaction - + Edit Transaction diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index c9580e9..f46d1f9 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -163,7 +163,7 @@ class Settings extends React.Component { editStatus, toggleCurrencyDisabled, isCurrencyDisabled, - changeNoReceipts + changeNoReceipts, } = this.props; if (this.props.returnValue === strings.Bluetooth) { From 68983bb614a0d85bf62f018dfb84df0eb817eec7 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Wed, 23 Oct 2019 16:58:08 +0800 Subject: [PATCH 05/29] Deletion of receiptline (Approve by manager feature) Applying Discount (Approve by manager feature) --- src/container/ListingContainer/index.js | 3 + src/container/LoginContainer/index.js | 1 + src/container/SalesContainer/index.js | 2 + src/container/SettingsContainer/index.js | 40 +++++- src/store/PosStore/PrinterStore.js | 19 +++ src/store/PosStore/syncInBackground.js | 14 +- src/store/StateStore/DefaultValues.js | 3 + src/store/StateStore/Models.js | 3 + src/stories/components/CompanyComponent.js | 31 ++--- src/stories/components/EntriesComponent.js | 11 +- src/stories/components/EntryComponent.js | 90 +++++++++++-- .../components/MoreSettingsComponent.js | 127 ++++++++++++++++++ src/stories/components/PrinterComponent.js | 2 +- src/stories/components/TabComponent.js | 1 + src/stories/components/ViewOrderComponent.js | 23 ++-- src/stories/screens/Sales/index.js | 2 + src/stories/screens/SalesList/index.js | 3 + src/stories/screens/Settings/index.js | 14 +- 18 files changed, 333 insertions(+), 56 deletions(-) create mode 100644 src/stories/components/MoreSettingsComponent.js diff --git a/src/container/ListingContainer/index.js b/src/container/ListingContainer/index.js index d215d7b..62506b0 100644 --- a/src/container/ListingContainer/index.js +++ b/src/container/ListingContainer/index.js @@ -706,6 +706,7 @@ export default class ListingContainer extends React.Component { const itemTab = ( 0 ? this.props.itemStore.queriedRows.slice().sort(sortByName) @@ -746,6 +747,7 @@ export default class ListingContainer extends React.Component { const categoryTab = ( 0) { - // Alert.alert("", this.props.printerStore.companySettings[0].name + " " + this.props.printerStore.companySettings[0].header + " " + this.props.printerStore.companySettings[0].footer) - // this.setState({ - // companyName: this.props.printerStore.companySettings[0].name.toString(), - // companyHeader: this.props.printerStore.companySettings[0].header.toString(), - // companyFooter: this.props.printerStore.companySettings[0].footer.toString(), - // }); this.props.stateStore.changeValue( "companyName", this.props.printerStore.companySettings[0].name.toString(), "Settings", ); + this.props.stateStore.changeValue( + "smallSizeIcon", + this.props.printerStore.companySettings[0].smallSizeIcon, + "Settings", + ); + this.props.stateStore.changeValue( + "mediumSizeIcon", + this.props.printerStore.companySettings[0].mediumSizeIcon, + "Settings", + ); + this.props.stateStore.changeValue( + "largeSizeIcon", + this.props.printerStore.companySettings[0].largeSizeIcon, + "Settings", + ); this.props.stateStore.changeValue( "tax", this.props.printerStore.companySettings[0].tax.toString(), @@ -155,7 +164,6 @@ export default class SettingsContainer extends React.Component { this.props.printerStore.rows[i]._id, "Settings", ); - BluetoothSerial.connect(this.props.printerStore.rows[i].macAddress) .then(() => { // this.setState({ @@ -822,6 +830,23 @@ export default class SettingsContainer extends React.Component { ], ); }; + toggleItemSize = size => { + const { stateStore } = this.props; + stateStore.changeValue("smallSizeIcon", size === "Small", "Settings"); + stateStore.changeValue("mediumSizeIcon", size === "Medium", "Settings"); + stateStore.changeValue("largeSizeIcon", size === "Large", "Settings"); + + if (this.props.printerStore.companySettings.length > 0) { + let company = this.props.printerStore.findCompany( + this.props.printerStore.companySettings[0]._id, + ); + company.edit({ + smallSizeIcon: size === "Small", + mediumSizeIcon: size === "Medium", + largeSizeIcon: size === "Large", + }); + } + }; render() { strings.setLanguage(currentLanguage().companyLanguage); const { @@ -850,6 +875,7 @@ export default class SettingsContainer extends React.Component { availableDevicesChangeValue={text => stateStore.changeValue("availableDevices", text, "Settings") } + toggleItemSize={size => this.toggleItemSize(size)} checkBoxValueOnChange={this.onCheckBoxValueOnChange} bluetoothScannerStatus={text => { stateStore.changeValue("checkBoxBluetoothValue", text, "Settings"); diff --git a/src/store/PosStore/PrinterStore.js b/src/store/PosStore/PrinterStore.js index f06906c..d92b654 100644 --- a/src/store/PosStore/PrinterStore.js +++ b/src/store/PosStore/PrinterStore.js @@ -77,6 +77,9 @@ export const Company = types tax: types.optional(types.string, "0"), countryCode: types.optional(types.string, "PHP"), currencyDisable: types.optional(types.boolean, false), + smallSizeIcon: types.optional(types.boolean, false), + mediumSizeIcon: types.optional(types.boolean, false), + largeSizeIcon: types.optional(types.boolean, true), hideCategory: types.optional(types.boolean, false), }) .preProcessSnapshot(snapshot => assignUUID(snapshot, "Company")) @@ -336,6 +339,16 @@ const Store = types if (!entries.rows[i].doc.changeNoReceipts) { entries.rows[i].doc.changeNoReceipts = "1"; } + if (!entries.rows[i].doc.smallSizeIcon) { + entries.rows[i].doc.smallSizeIcon = false; + } + if (!entries.rows[i].doc.mediumSizeIcon) { + entries.rows[i].doc.mediumSizeIcon = false; + } + if (!entries.rows[i].doc.largeSizeIcon) { + entries.rows[i].doc.largeSizeIcon = false; + } + self.addCompany(JSON.parse(JSON.stringify(entries.rows[i].doc))); } } @@ -349,6 +362,9 @@ const Store = types tax: "0", countryCode: "PHP", currencyDisable: false, + smallSizeIcon: false, + mediumSizeIcon: false, + largeSizeIcon: true, }); } } else { @@ -361,6 +377,9 @@ const Store = types tax: "0", countryCode: "PHP", currencyDisable: false, + smallSizeIcon: false, + mediumSizeIcon: false, + largeSizeIcon: true, }); } }); diff --git a/src/store/PosStore/syncInBackground.js b/src/store/PosStore/syncInBackground.js index a51909a..8ec7d63 100644 --- a/src/store/PosStore/syncInBackground.js +++ b/src/store/PosStore/syncInBackground.js @@ -28,9 +28,15 @@ export function syncObjectValues(status, store, jobStatus) { const syncInfo = { deviceId: store.stateStore.deviceId, - url: protocol + store.printerStore.sync[0].url, - user_name: store.printerStore.sync[0].user_name, - password: store.printerStore.sync[0].password, + url: store.printerStore.sync[0].url + ? protocol + store.printerStore.sync[0].url + : "", + user_name: store.printerStore.sync[0].user_name + ? store.printerStore.sync[0].user_name + : "", + password: store.printerStore.sync[0].password + ? store.printerStore.sync[0].password + : "", }; store.syncStore @@ -206,7 +212,7 @@ export async function itemSync(itemObject, store) { category: categoryId, taxes: "[]", dateUpdated: Date.now(), - syncStatus: itemObject.syncObject.id !== null ? true : false, + syncStatus: itemObject.syncObject.id !== null, }; itemObject.syncObject.id !== null ? (objecct_to_add._id = itemObject.syncObject.id) diff --git a/src/store/StateStore/DefaultValues.js b/src/store/StateStore/DefaultValues.js index c07bb85..9b049b9 100644 --- a/src/store/StateStore/DefaultValues.js +++ b/src/store/StateStore/DefaultValues.js @@ -65,6 +65,9 @@ export const settings = { currentAddress: "", companyName: "", changeNoReceipts: "1", + smallSizeIcon: false, + mediumSizeIcon: false, + largeSizeIcon: true, tax: "0", companyHeader: "", companyFooter: "", diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index d71cab4..77707b7 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -71,6 +71,9 @@ export const ModelSettings = { companyFooter: types.optional(types.string, ""), companyCurrency: types.optional(types.string, ""), checkBoxBluetoothValue: types.optional(types.boolean, false), + smallSizeIcon: types.optional(types.boolean, false), + mediumSizeIcon: types.optional(types.boolean, false), + largeSizeIcon: types.optional(types.boolean, true), checkBoxValue: types.optional(types.string, ""), attendants: types.optional(types.string, "[]"), // attendantsInfo: {}, diff --git a/src/stories/components/CompanyComponent.js b/src/stories/components/CompanyComponent.js index 8559dca..201a658 100644 --- a/src/stories/components/CompanyComponent.js +++ b/src/stories/components/CompanyComponent.js @@ -79,15 +79,14 @@ class CompanyComponent extends React.PureComponent { - - - - + + + @@ -103,8 +102,6 @@ class CompanyComponent extends React.PureComponent { - - {strings.Tax} @@ -123,13 +120,7 @@ class CompanyComponent extends React.PureComponent { - + { return ( ); }; + render() { + let numCol = + this.props.listStatus === "Sales" + ? this.props.company.smallSizeIcon + ? 4 + : 3 + : 2; return ( index} renderItem={this._renderItem} diff --git a/src/stories/components/EntryComponent.js b/src/stories/components/EntryComponent.js index 72940a3..6eab602 100644 --- a/src/stories/components/EntryComponent.js +++ b/src/stories/components/EntryComponent.js @@ -11,13 +11,34 @@ export default class EntryComponent extends React.PureComponent { let mc = new MoneyCurrency( this.props.currency ? this.props.currency : "PHP", ); + const { smallSizeIcon, mediumSizeIcon } = this.props.company; + const { listStatus } = this.props; + const height = Dimensions.get("window").height; return ( - + {this.props.value.colorAndShape ? ( ) : ( )} @@ -79,14 +131,28 @@ export default class EntryComponent extends React.PureComponent { style={{ alignItems: "center", justifyContent: "center", - width: Dimensions.get("window").width * 0.12, - height: Dimensions.get("window").height * 0.08, + width: + listStatus === "Sales" + ? smallSizeIcon + ? width * 0.06 + : mediumSizeIcon + ? width * 0.09 + : width * 0.12 + : width * 0.12, + height: height * 0.08, }} > + + + + + More Settings + + + + + + + + Item Icon Size + + + toggleItemSize("Small")} + // disabled={!this.props.editStatus} + /> + + + toggleItemSize("Medium")} + + // disabled={!this.props.editStatus} + /> + + + toggleItemSize("Large")} + + // disabled={!this.props.editStatus} + /> + + + + ); + } +} +const styles = StyleSheet.create({ + card: { + width: "100%", + alignSelf: "center", + }, + cardItem: { + marginBottom: 15, + backgroundColor: "#4b4c9d", + }, + col: { + alignSelf: "center", + }, + titleText: { + color: "white", + fontSize: Dimensions.get("window").width * 0.02, + }, + icon: { + color: "white", + marginLeft: 10, + }, + viewRight: { + flexDirection: "row", + alignSelf: "flex-end", + }, + cardItemHelp: { + borderColor: "gray", + borderBottomWidth: 0.5, + }, + cardItemText: { + marginLeft: 10, + fontWeight: "bold", + color: "gray", + }, + cardItemView: { + width: "50%", + marginLeft: 3, + }, + cardItemViewTextAreaTax: { + width: "50%", + marginLeft: 3, + }, + cardItemViewTextArea: { + width: "60%", + }, + pickerView: { + borderWidth: 1, + borderColor: "#cfcfcf", + }, + picker: { + width: "100%", + }, + text: { + fontWeight: "bold", + }, +}); + +export default MoreSettingsComponent; diff --git a/src/stories/components/PrinterComponent.js b/src/stories/components/PrinterComponent.js index 3e487ad..e9dd48a 100644 --- a/src/stories/components/PrinterComponent.js +++ b/src/stories/components/PrinterComponent.js @@ -30,7 +30,7 @@ const PrinterComponent = props => { const connectionStatus = ( - {props.connection ? strings.Online : props.connectionStatus} + {props.connection ? "Online" : props.connectionStatus} ); diff --git a/src/stories/components/TabComponent.js b/src/stories/components/TabComponent.js index c77c6b0..31a1e70 100644 --- a/src/stories/components/TabComponent.js +++ b/src/stories/components/TabComponent.js @@ -6,6 +6,7 @@ const TabComponent = props => ( props.onClick(index)} diff --git a/src/stories/components/ViewOrderComponent.js b/src/stories/components/ViewOrderComponent.js index c552174..f6c40ee 100644 --- a/src/stories/components/ViewOrderComponent.js +++ b/src/stories/components/ViewOrderComponent.js @@ -21,18 +21,19 @@ let strings = new LocalizedStrings(translation); class ViewOrderComponent extends React.PureComponent { renderOrderItem = ({ item, index }) => { const { onTableClick, onTableLongPress } = this.props; - return ( - - ); + if (!item.is_finished) { + return ( + + ); + } }; - renderOrders() { const { orders } = this.props; diff --git a/src/stories/screens/Sales/index.js b/src/stories/screens/Sales/index.js index 2386cad..c886965 100644 --- a/src/stories/screens/Sales/index.js +++ b/src/stories/screens/Sales/index.js @@ -135,6 +135,7 @@ class Sales extends React.PureComponent { onCancelOrder, isCurrencyDisabled, listStatus, + company, } = this.props; return ( @@ -166,6 +167,7 @@ class Sales extends React.PureComponent { this.renderOrder() ) : ( ); } - + if (this.props.returnValue === "More...") { + return ( + toggleItemSize(size)} + /> + ); + } return null; }; @@ -293,6 +303,7 @@ class Settings extends React.Component { { name: strings.Bluetooth }, { name: strings.Company }, { name: strings.Sync }, + { name: "More..." }, ]; if (this.props.attendant && this.props.attendant.role === "Owner") { @@ -302,6 +313,7 @@ class Settings extends React.Component { { name: strings.Attendant }, { name: strings.Sync }, { name: strings.Queueing }, + { name: "More..." }, ]; } strings.setLanguage(currentLanguage().companyLanguage); From fcbaa54a9d75a7620859a53639be516021b6cfae Mon Sep 17 00:00:00 2001 From: jiloysss Date: Thu, 24 Oct 2019 10:45:43 +0800 Subject: [PATCH 06/29] Added Overall Tax Checkbox --- src/container/ListingContainer/index.js | 1 - src/container/SalesContainer/index.js | 8 ++-- src/container/SettingsContainer/index.js | 7 +++ src/store/PosStore/PrinterStore.js | 1 + src/store/StateStore/StateStore.js | 7 +++ src/stories/components/CompanyComponent.js | 50 ++++++++++++++-------- src/stories/screens/InputItem/index.js | 4 +- src/stories/screens/Settings/index.js | 4 ++ 8 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/container/ListingContainer/index.js b/src/container/ListingContainer/index.js index 62506b0..60457c1 100644 --- a/src/container/ListingContainer/index.js +++ b/src/container/ListingContainer/index.js @@ -350,7 +350,6 @@ export default class ListingContainer extends React.Component { JSON.stringify(index.taxesValue), "Listing", ); - if (this.props.stateStore.listing_state[0].itemMaintenanceStatus) { this.props.itemStore.setItem(index); } else { diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 2f24be8..3eebbea 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -83,7 +83,7 @@ export default class SalesContainer extends React.Component { "Sales", ); } - this.viewOrders(); + this.viewOrders("willMount"); } async getBluetoothState() { @@ -691,7 +691,7 @@ export default class SalesContainer extends React.Component { this.props.stateStore.changeValue("quantityModalVisible", true, "Sales"); }; - viewOrders = () => { + viewOrders = status => { const { setViewingOrder, setLoadingOrder, @@ -699,8 +699,8 @@ export default class SalesContainer extends React.Component { queueOrigin, } = this.props.stateStore; - setViewingOrder(true); - setLoadingOrder(true); + setViewingOrder(!status); + setLoadingOrder(!status); const url = `${queueOrigin}/api/v1/orders/`; diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index 1055fef..70023f7 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -141,6 +141,9 @@ export default class SettingsContainer extends React.Component { this.props.stateStore.changeCompanyCheckBox( this.props.printerStore.companySettings[0].currencyDisable, ); + this.props.stateStore.changeOverallTax( + this.props.printerStore.companySettings[0].enableOverallTax, + ); } for (let i = 0; i < this.props.printerStore.rows.length; i += 1) { if (this.props.printerStore.rows[i].defaultPrinter) { @@ -381,6 +384,7 @@ export default class SettingsContainer extends React.Component { header: this.props.stateStore.settings_state[0].companyHeader, footer: this.props.stateStore.settings_state[0].companyFooter, countryCode: this.props.stateStore.settings_state[0].companyCountry, + enableOverallTax: this.props.stateStore.enableOverallTax, currencyDisable: this.props.stateStore.isCurrencyDisabled, changeNoReceipts: this.props.stateStore.settings_state[0] .changeNoReceipts, @@ -395,6 +399,7 @@ export default class SettingsContainer extends React.Component { footer: this.props.stateStore.settings_state[0].companyFooter, countryCode: this.props.stateStore.settings_state[0].companyCountry, currencyDisable: this.props.stateStore.isCurrencyDisabled, + enableOverallTax: this.props.stateStore.enableOverallTax, changeNoReceipts: this.props.stateStore.settings_state[0] .changeNoReceipts, }); @@ -949,7 +954,9 @@ export default class SettingsContainer extends React.Component { toggleTailOrder={stateStore.toggleTailOrder} onQueueSave={this.onQueueSave} toggleCurrencyDisabled={this.props.stateStore.toggleCurrencyDisabled} + toggleEnableOverallTax={this.props.stateStore.toggleEnableOverallTax} isCurrencyDisabled={stateStore.isCurrencyDisabled} + enableOverallTax={stateStore.enableOverallTax} // Queue Settings isEditingQueue={stateStore.isEditingQueue} setQueueEditing={stateStore.setQueueEditing} diff --git a/src/store/PosStore/PrinterStore.js b/src/store/PosStore/PrinterStore.js index d92b654..50c8873 100644 --- a/src/store/PosStore/PrinterStore.js +++ b/src/store/PosStore/PrinterStore.js @@ -77,6 +77,7 @@ export const Company = types tax: types.optional(types.string, "0"), countryCode: types.optional(types.string, "PHP"), currencyDisable: types.optional(types.boolean, false), + enableOverallTax: types.optional(types.boolean, false), smallSizeIcon: types.optional(types.boolean, false), mediumSizeIcon: types.optional(types.boolean, false), largeSizeIcon: types.optional(types.boolean, true), diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index dea1b18..d2111ca 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -42,6 +42,7 @@ const StateStore = types useDescription: types.optional(types.boolean, false), isHttps: types.optional(types.boolean, false), isCurrencyDisabled: types.optional(types.boolean, false), + enableOverallTax: types.optional(types.boolean, false), deviceId: types.optional(types.string, ""), isStackItem: types.optional(types.boolean, false), @@ -200,6 +201,9 @@ const StateStore = types toggleCurrencyDisabled() { self.isCurrencyDisabled = !self.isCurrencyDisabled; }, + toggleEnableOverallTax() { + self.enableOverallTax = !self.enableOverallTax; + }, setDeviceId(deviceId) { self.deviceId = deviceId; }, @@ -209,6 +213,9 @@ const StateStore = types changeCompanyCheckBox(isCurrencyDisabled) { self.isCurrencyDisabled = isCurrencyDisabled; }, + changeOverallTax(overallTax) { + self.enableOverallTax = overallTax; + }, })); const Store = StateStore.create({}); diff --git a/src/stories/components/CompanyComponent.js b/src/stories/components/CompanyComponent.js index 201a658..4d54be9 100644 --- a/src/stories/components/CompanyComponent.js +++ b/src/stories/components/CompanyComponent.js @@ -31,7 +31,12 @@ class CompanyComponent extends React.PureComponent { } render() { - const { toggleCurrencyDisabled, isCurrencyDisabled } = this.props; + const { + toggleCurrencyDisabled, + isCurrencyDisabled, + enableOverallTax, + toggleEnableOverallTax, + } = this.props; strings.setLanguage(currentLanguage().companyLanguage); const countryCodes = Constants.map(country => ( @@ -79,31 +84,18 @@ class CompanyComponent extends React.PureComponent { - + - + - - {strings.Language} - - - {languages} - - - - {strings.Tax} + {strings.Tax}(%) - + + + + + + + + + {strings.Language} + + + {languages} + diff --git a/src/stories/screens/InputItem/index.js b/src/stories/screens/InputItem/index.js index 3afcd88..14dabda 100644 --- a/src/stories/screens/InputItem/index.js +++ b/src/stories/screens/InputItem/index.js @@ -38,24 +38,24 @@ export default class InputItem extends React.Component { if (data) { const priceCurrency = formatNumber(data.price); - this.setState({ name: data.name, price: priceCurrency, sku: data.sku, + tax: data.tax.toString(), barcode: data.barcode, category: data.category, soldBy: data.soldBy, colorAndShape: JSON.parse(data.colorAndShape), }); } - if (dataDetails) { const dataDupBarcode = JSON.parse(dataDetails); this.setState({ name: dataDupBarcode.name, price: dataDupBarcode.price.toString(), sku: dataDupBarcode.sku, + tax: dataDupBarcode.tax, barcode: dataDupBarcode.barcode, category: dataDupBarcode.category, soldBy: dataDupBarcode.soldBy, diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index 356b5d0..1462262 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -166,6 +166,8 @@ class Settings extends React.Component { isCurrencyDisabled, changeNoReceipts, toggleItemSize, + toggleEnableOverallTax, + enableOverallTax, } = this.props; if (this.props.returnValue === strings.Bluetooth) { @@ -213,7 +215,9 @@ class Settings extends React.Component { editStatus={editStatus} onCompanyEdit={changeEditStatus} toggleCurrencyDisabled={toggleCurrencyDisabled} + toggleEnableOverallTax={toggleEnableOverallTax} isCurrencyDisabled={isCurrencyDisabled} + enableOverallTax={enableOverallTax} onCompanySave={() => { changeEditStatus(false); onCompanySave(); From bd6ba613b719fca46220eb7bad5979f5bf6a9969 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Tue, 29 Oct 2019 14:05:31 +0800 Subject: [PATCH 07/29] Wallet --- src/boot/configureStore.js | 3 + src/boot/index.js | 3 + src/container/PaymentContainer/index.js | 59 +++++++--- src/container/SalesContainer/index.js | 18 ++- src/container/SettingsContainer/index.js | 12 +- src/store/PosStore/ReceiptStore.js | 15 +++ src/store/PosStore/SyncStore.js | 9 +- src/store/PosStore/WalletStore.js | 103 ++++++++++++++++++ src/store/PosStore/syncInBackground.js | 63 ++++++++++- src/store/StateStore/DefaultValues.js | 1 + src/store/StateStore/Models.js | 1 + src/stories/components/EntryComponent.js | 1 + .../components/MoreSettingsComponent.js | 2 - .../components/SummaryModalComponent.js | 19 +++- src/stories/components/TotalLineComponent.js | 4 +- src/stories/screens/Payment/index.js | 12 ++ src/stories/screens/Sales/index.js | 4 + src/stories/screens/SalesList/index.js | 15 ++- src/stories/screens/SalesReceipt/index.js | 10 +- src/utils.js | 1 + 20 files changed, 305 insertions(+), 50 deletions(-) create mode 100644 src/store/PosStore/WalletStore.js diff --git a/src/boot/configureStore.js b/src/boot/configureStore.js index af6d28b..96decce 100644 --- a/src/boot/configureStore.js +++ b/src/boot/configureStore.js @@ -11,6 +11,7 @@ import ShiftStore from "@posStore/ShiftStore"; import TaxesStore from "@posStore/TaxesStore"; import SyncStore from "@posStore/SyncStore"; import RoleStore from "@posStore/RoleStore"; +import WalletStore from "@posStore/WalletStore"; import ShiftReportsStore from "@posStore/ShiftReportsStore"; import LoginStore from "@viewStore/LoginViewStore"; import SignupStore from "@viewStore/SignupViewStore"; @@ -34,6 +35,7 @@ export default function() { const shiftStore = ShiftStore; const syncStore = SyncStore; const signupForm = SignupStore; + const walletStore = WalletStore; const roleStore = RoleStore; const shiftReportsStore = ShiftReportsStore; const lostPasswordForm = LostPasswordStore; @@ -59,5 +61,6 @@ export default function() { stateStore, headSyncStore, roleStore, + walletStore, }; } diff --git a/src/boot/index.js b/src/boot/index.js index 9b2d2b9..129c261 100644 --- a/src/boot/index.js +++ b/src/boot/index.js @@ -62,6 +62,9 @@ export default function() { stores.stateStore.changeCompanyCheckBox( stores.printerStore.companySettings[0].currencyDisable, ); + stores.stateStore.changeOverallTax( + stores.printerStore.companySettings[0].enableOverallTax, + ); }); return app(stores); diff --git a/src/container/PaymentContainer/index.js b/src/container/PaymentContainer/index.js index 332c58a..343f2a2 100644 --- a/src/container/PaymentContainer/index.js +++ b/src/container/PaymentContainer/index.js @@ -29,6 +29,7 @@ const moment = require("moment"); "shiftStore", "attendantStore", "stateStore", + "walletStore", ) @observer export default class PaymentContainer extends React.Component { @@ -274,7 +275,10 @@ export default class PaymentContainer extends React.Component { } this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, + this.props.stateStore.enableOverallTax + ? this.props.receiptStore.defaultReceipt.get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, ); // this.props.receiptStore.defaultReceipt.clear(); @@ -294,8 +298,11 @@ export default class PaymentContainer extends React.Component { ); let discountValueForDisplay = this.props.receiptStore .defaultReceipt.discounts; - let taxesValueForDisplay = this.props.receiptStore - .defaultReceipt.get_tax_total; + let taxesValueForDisplay = this.props.stateStore + .enableOverallTax + ? this.props.receiptStore.defaultReceipt.get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item; this.props.receiptStore.newReceipt( this.props.printerStore.companySettings[0].tax, ); @@ -658,7 +665,10 @@ export default class PaymentContainer extends React.Component { let taxValue = strings.Tax; let tax = formatNumber( parseFloat( - this.props.receiptStore.defaultReceipt.get_tax_total, + this.props.stateStore.enableOverallTax + ? this.props.receiptStore.defaultReceipt.get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, 10, ), ).toString(); @@ -737,8 +747,11 @@ export default class PaymentContainer extends React.Component { 10, ) + parseFloat( - this.props.receiptStore.defaultReceipt - .get_tax_total, + this.props.stateStore.enableOverallTax + ? this.props.receiptStore.defaultReceipt + .get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, 10, ), ).toString(); @@ -788,8 +801,11 @@ export default class PaymentContainer extends React.Component { 10, ) + parseFloat( - this.props.receiptStore.defaultReceipt - .get_tax_total, + this.props.stateStore.enableOverallTax + ? this.props.receiptStore.defaultReceipt + .get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, 10, )), 10, @@ -902,7 +918,10 @@ export default class PaymentContainer extends React.Component { ); this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, + this.props.stateStore.enableOverallTax + ? this.props.receiptStore.defaultReceipt.get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, ); // add to row @@ -942,7 +961,10 @@ export default class PaymentContainer extends React.Component { ); this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, + this.props.stateStore.enableOverallTax + ? this.props.receiptStore.defaultReceipt.get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, ); // add to row @@ -984,7 +1006,10 @@ export default class PaymentContainer extends React.Component { ); this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.receiptStore.defaultReceipt.get_tax_total, + this.props.stateStore.enableOverallTax + ? this.props.receiptStore.defaultReceipt.get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, ); // add to row @@ -1049,8 +1074,11 @@ export default class PaymentContainer extends React.Component { ); let discountValueForDisplay = this.props.receiptStore .defaultReceipt.discounts; - let taxesValueForDisplay = this.props.receiptStore - .defaultReceipt.get_tax_total; + let taxesValueForDisplay = this.props.stateStore + .enableOverallTax + ? this.props.receiptStore.defaultReceipt.get_tax_total + : this.props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item; this.props.receiptStore.newReceipt( this.props.printerStore.companySettings[0].tax, ); @@ -1225,7 +1253,9 @@ export default class PaymentContainer extends React.Component { this.props.stateStore.changeValue("customerPhoneNumber", "", "Payment"); this.props.stateStore.changeValue("customerNotes", "", "Payment"); }; - + onChangeCardNumber = text => { + this.props.stateStore.changeValue("walletCardNumber", text, "Payment"); + }; render() { strings.setLanguage(currentLanguage().companyLanguage); return ( @@ -1261,6 +1291,7 @@ export default class PaymentContainer extends React.Component { } useDefaultCustomer={this.props.stateStore.useDefaultCustomer} isCurrencyDisabled={this.props.stateStore.isCurrencyDisabled} + onChangeCardNumber={this.onChangeCardNumber} /> ); } diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 3eebbea..794cb35 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -226,10 +226,16 @@ export default class SalesContainer extends React.Component { onDeleteReceiptLine = () => { const { hideDeleteDialog } = this.props.stateStore; hideDeleteDialog(); - - this.props.stateStore.changeConfirmation("AllReceiptLine"); - const { changeValue } = this.props.stateStore; - changeValue("confirmation", true, "Sales"); + if (this.props.attendantStore.defaultAttendant.canApprove) { + const { unselectReceiptLine, defaultReceipt } = this.props.receiptStore; + unselectReceiptLine(); + defaultReceipt.clear(); + hideDeleteDialog(); + } else { + this.props.stateStore.changeConfirmation("AllReceiptLine"); + const { changeValue } = this.props.stateStore; + changeValue("confirmation", true, "Sales"); + } }; onBarcodeClick = () => { @@ -519,11 +525,13 @@ export default class SalesContainer extends React.Component { summaryDialog() { const { previousReceipt } = this.props.receiptStore; + const { enableOverallTax } = this.props.stateStore; const { cash, change } = this.props.stateStore.sales_state[0]; const { countryCode } = this.props.printerStore.companySettings[0]; return ( { unselectReceiptLine(); @@ -1024,6 +1031,7 @@ export default class SalesContainer extends React.Component { onChangeTable={this.onChangeTable} onReprintOrder={this.onReprintOrder} isCurrencyDisabled={this.props.stateStore.isCurrencyDisabled} + enableOverallTax={this.props.stateStore.enableOverallTax} /> ); diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index 70023f7..3d026e4 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -428,6 +428,14 @@ export default class SettingsContainer extends React.Component { }); } }; + onSaveNoReceipts = receiptNo => { + const { stateStore, printerStore } = this.props; + stateStore.changeValue("changeNoReceipts", receiptNo, "Settings"); + let company = printerStore.findCompany(printerStore.companySettings[0]._id); + company.edit({ + changeNoReceipts: receiptNo, + }); + }; bluetoothScannerStatus(text) { if (this.props.printerStore.bluetooth.length > 0) { let bluetoothScanner = this.props.printerStore.findBluetoothScanner( @@ -895,9 +903,7 @@ export default class SettingsContainer extends React.Component { changeName={text => stateStore.changeValue("companyName", text, "Settings") } - changeNoReceipts={text => - stateStore.changeValue("changeNoReceipts", text, "Settings") - } + changeNoReceipts={this.onSaveNoReceipts} changeTax={text => stateStore.changeValue("tax", text, "Settings")} changeCountry={text => this.onChangeCurrency(text)} changeHeader={text => diff --git a/src/store/PosStore/ReceiptStore.js b/src/store/PosStore/ReceiptStore.js index d7e9796..6fc7ef8 100644 --- a/src/store/PosStore/ReceiptStore.js +++ b/src/store/PosStore/ReceiptStore.js @@ -26,6 +26,7 @@ export const ReceiptLine = types qty: types.number, commission_details: types.optional(types.string, "[]"), discount_rate: types.optional(types.number, 0), + tax: types.optional(types.number, 0), discountType: types.optional(types.string, "percentage"), }) .preProcessSnapshot(snapshot => assignUUID(snapshot, "ReceiptLine")) @@ -43,6 +44,9 @@ export const ReceiptLine = types } return self.price * self.qty; }, + get tax_total() { + return self.total * (self.tax / 100); + }, })) .actions(self => ({ setQuantity(qty) { @@ -198,6 +202,17 @@ export const Receipt = types } return 0; }, + get get_tax_total_based_on_each_item() { + if (self.lines.length !== 0) { + let total = 0; + for (let i = 0; i < self.lines.length; i++) { + total = total + self.lines[i].tax_total; + } + + return total; + } + return 0; + }, get linesLength() { return self.lines.length; }, diff --git a/src/store/PosStore/SyncStore.js b/src/store/PosStore/SyncStore.js index 6d99a5f..c42bd05 100644 --- a/src/store/PosStore/SyncStore.js +++ b/src/store/PosStore/SyncStore.js @@ -1,14 +1,7 @@ import { types } from "mobx-state-tree"; import { openAndSyncDB, sync, saveSnapshotToDB } from "./DbFunctions"; import { assignUUID } from "./Utils"; -// let Item = openAndSyncDB("items"); -// let Category = openAndSyncDB("categories"); -// let Discount = openAndSyncDB("discounts"); -// let shiftDb = openAndSyncDB("categories"); -// let attendantDb = openAndSyncDB("categories"); -// let shiftReportDb = openAndSyncDB("categories"); -// let receiptDb = openAndSyncDB("categories"); -// let paymentDb = openAndSyncDB("categories"); + let trash = openAndSyncDB("trash", true); export const Trash = types .model("Trash", { diff --git a/src/store/PosStore/WalletStore.js b/src/store/PosStore/WalletStore.js new file mode 100644 index 0000000..9526bca --- /dev/null +++ b/src/store/PosStore/WalletStore.js @@ -0,0 +1,103 @@ +import { assignUUID } from "./Utils"; +import { types } from "mobx-state-tree"; +import { openAndSyncDB, syncDB } from "./DbFunctions"; + +let db = openAndSyncDB("wallet", true); +let rowsOptions = {}; + +export const Wallet = types + .model("Wallet", { + _id: types.identifier(), + wallet_card_number: types.string, + prepaid_balance: types.optional(types.number, 0), + credit_limit: types.optional(types.number, 0), + expiry_date: types.optional(types.Date, Date.now), + syncStatus: types.optional(types.boolean, false), + }) + .preProcessSnapshot(snapshot => assignUUID(snapshot, "Wallet")) + .actions(self => ({ + postProcessSnapshot(snapshot) { + let updateObj = false; + db.upsert(snapshot._id, function(doc) { + if (!doc._id) { + doc = snapshot; + updateObj = true; + } else { + Object.keys(snapshot).forEach(function(key) { + if (!(key === "_rev")) { + if (doc[key] !== snapshot[key]) { + doc[key] = snapshot[key]; + updateObj = true; + } + } + }); + } + if (updateObj) { + return doc; + } else { + return updateObj; + } + }); + }, + edit(data) { + Object.keys(data).forEach(key => { + if (key !== "_id") { + self[key] = data[key]; + } + }); + }, + })); + +const WalletStore = types + .model("WalletStore", { + rows: types.optional(types.array(Wallet), []), + }) + .actions(self => ({ + initSync(session) { + syncDB(db, "wallet", session, () => {}); + }, + add(data) { + self.rows.push(data); + }, + destroyDb() { + db.destroy().then(function() { + db = openAndSyncDB("wallet", true); + rowsOptions = {}; + }); + }, + find(id) { + let obj = self.rows.find(data => { + return data._id === id; + }); + + if (obj) { + return obj; + } else { + db.get(id).then(doc => { + return Wallet.create(JSON.parse(JSON.stringify(doc))); + }); + } + return null; + }, + getFromDb(numberRows) { + rowsOptions.limit = numberRows; + rowsOptions.include_docs = true; + db.allDocs(rowsOptions).then(entries => { + if (entries && entries.rows.length > 0) { + rowsOptions.startKey = entries.rows[entries.rows.length - 1].id; + rowsOptions.skip = 1; + for (let i = 0; i < entries.rows.length; i++) { + if (entries.rows[i].doc._id) { + entries.rows[i].doc.dateUpdated = Date.now(); + entries.rows[i].doc.syncStatus = false; + self.add(JSON.parse(JSON.stringify(entries.rows[i].doc))); + } + } + } + }); + }, + })); + +const walletStore = WalletStore.create({}); + +export default walletStore; diff --git a/src/store/PosStore/syncInBackground.js b/src/store/PosStore/syncInBackground.js index 8ec7d63..577f3b2 100644 --- a/src/store/PosStore/syncInBackground.js +++ b/src/store/PosStore/syncInBackground.js @@ -28,9 +28,10 @@ export function syncObjectValues(status, store, jobStatus) { const syncInfo = { deviceId: store.stateStore.deviceId, - url: store.printerStore.sync[0].url - ? protocol + store.printerStore.sync[0].url - : "", + url: + store.printerStore.sync[0].url !== undefined + ? protocol + store.printerStore.sync[0].url + : "", user_name: store.printerStore.sync[0].user_name ? store.printerStore.sync[0].user_name : "", @@ -129,6 +130,10 @@ export async function itemSync(itemObject, store) { itemObject.syncObject.standard_rate !== null ? itemObject.syncObject.standard_rate : 0, + tax: + itemObject.syncObject.tax_rate !== null + ? itemObject.syncObject.tax_rate + : 0, sku: itemObject.syncObject.sku !== null ? itemObject.syncObject.sku : "", barcode: itemObject.syncObject.barcode === null || @@ -181,6 +186,10 @@ export async function itemSync(itemObject, store) { itemObject.syncObject.standard_rate !== null ? itemObject.syncObject.standard_rate : 0, + tax: + itemObject.syncObject.tax_rate !== null + ? itemObject.syncObject.tax_rate + : 0, sku: itemObject.syncObject.sku !== null ? itemObject.syncObject.sku : "", barcode: itemObject.syncObject.barcode !== null && @@ -411,7 +420,55 @@ export async function customerSync(customerObject, store) { } } } +export async function walletSync(walletObject, store) { + if (walletObject.syncObject.id !== null) { + const walletObjectResult = await store.walletStore.find( + walletObject.syncObject.id, + ); + if (walletObjectResult) { + walletObjectResult.edit({ + _id: walletObjectResult.syncObject.id, + wallet_card_number: + walletObjectResult.syncObject.wallet_card_number !== null + ? walletObjectResult.syncObject.wallet_card_number + : "", + prepaid_balance: + walletObjectResult.syncObject.prepaid_balance !== null + ? walletObjectResult.syncObject.prepaid_balance + : 0, + credit_limit: + walletObjectResult.syncObject.credit_limit !== null + ? walletObjectResult.syncObject.credit_limit + : 0, + expiry_date: + walletObjectResult.syncObject.expiry_date !== null + ? walletObjectResult.syncObject.expiry_date + : Date.now(), + }); + } else { + store.walletStore.add({ + _id: walletObjectResult.syncObject.id, + wallet_card_number: + walletObjectResult.syncObject.wallet_card_number !== null + ? walletObjectResult.syncObject.wallet_card_number + : "", + prepaid_balance: + walletObjectResult.syncObject.prepaid_balance !== null + ? walletObjectResult.syncObject.prepaid_balance + : 0, + credit_limit: + walletObjectResult.syncObject.credit_limit !== null + ? walletObjectResult.syncObject.credit_limit + : 0, + expiry_date: + walletObjectResult.syncObject.expiry_date !== null + ? walletObjectResult.syncObject.expiry_date + : Date.now(), + }); + } + } +} export async function companySync(companyObject, store) { const companyObjectResult = await store.printerStore.findCompany( store.printerStore.companySettings[0]._id, diff --git a/src/store/StateStore/DefaultValues.js b/src/store/StateStore/DefaultValues.js index 9b049b9..11cd92d 100644 --- a/src/store/StateStore/DefaultValues.js +++ b/src/store/StateStore/DefaultValues.js @@ -55,6 +55,7 @@ export const payment = { customerName: "", customerEmail: "", customerPhoneNumber: "", + walletCardNumber: "", customerNotes: "", arrayObjects: JSON.stringify([]), }; diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index 77707b7..448a39d 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -55,6 +55,7 @@ export const ModelPayment = { modalVisible: types.optional(types.boolean, false), customerName: types.optional(types.string, ""), customerEmail: types.optional(types.string, ""), + walletCardNumber: types.optional(types.string, ""), customerPhoneNumber: types.optional(types.string, ""), customerNotes: types.optional(types.string, ""), arrayObjects: types.optional(types.string, "[]"), diff --git a/src/stories/components/EntryComponent.js b/src/stories/components/EntryComponent.js index 6eab602..5700f55 100644 --- a/src/stories/components/EntryComponent.js +++ b/src/stories/components/EntryComponent.js @@ -155,6 +155,7 @@ export default class EntryComponent extends React.PureComponent { : height * 0.022, color: "white", textAlign: "center", + fontWeight: "bold", }} > {this.props.useDescription diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index ed1d76f..fdab7ab 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -27,8 +27,6 @@ class MoreSettingsComponent extends React.PureComponent { - {mc.moneyFormat( - formatNumber( - parseFloat(this.props.details.get_tax_total), - ), - )} + {this.props.enableOverallTax + ? mc.moneyFormat( + formatNumber( + parseFloat(this.props.details.get_tax_total), + ), + ) + : mc.moneyFormat( + formatNumber( + parseFloat( + this.props.details + .get_tax_total_based_on_each_item, + ), + ), + )} diff --git a/src/stories/components/TotalLineComponent.js b/src/stories/components/TotalLineComponent.js index fc80443..f41e1e7 100644 --- a/src/stories/components/TotalLineComponent.js +++ b/src/stories/components/TotalLineComponent.js @@ -25,7 +25,9 @@ const TotalLineComponent = props => ( {strings.Tax}{" "} {parseFloat(props.receipt.taxesValue) > 0 - ? "(" + props.receipt.taxesValue.toString() + "%)" + ? props.enableOverallTax + ? "(" + props.receipt.taxesValue.toString() + "%)" + : "" : ""} diff --git a/src/stories/screens/Payment/index.js b/src/stories/screens/Payment/index.js index 8f45254..9e8a5bd 100644 --- a/src/stories/screens/Payment/index.js +++ b/src/stories/screens/Payment/index.js @@ -34,6 +34,7 @@ const PAYMENT_ITEMS = [ , , , + , ]; export default class Payment extends React.PureComponent { @@ -172,6 +173,17 @@ export default class Payment extends React.PureComponent { style={styles.printerStyle} /> + {this.props.values.selected === "Wallet" ? ( + + + + + + + ) : null} diff --git a/src/stories/screens/Sales/index.js b/src/stories/screens/Sales/index.js index c886965..1c718b0 100644 --- a/src/stories/screens/Sales/index.js +++ b/src/stories/screens/Sales/index.js @@ -20,6 +20,8 @@ class Sales extends React.PureComponent { onItemClick = index => this.props.onItemClick(index); onReceiptLineDelete = index => this.props.onReceiptLineDelete(index); onCategoryClick = (id, index) => this.props.onCategoryClick(id, index); + navigate = () => this.props.navigation.navigate("DrawerOpen"); + onSearchClick = () => this.props.onSearchClick(true); renderOrder() { const { @@ -136,6 +138,7 @@ class Sales extends React.PureComponent { isCurrencyDisabled, listStatus, company, + enableOverallTax, } = this.props; return ( @@ -199,6 +202,7 @@ class Sales extends React.PureComponent { this.props.onItemClick(index); onPressCategory = (id, index) => this.props.onCategoryClick(id, index); - onSearchClick = () => this.props.onSearchClick(true); - navigate = () => this.props.navigation.navigate("DrawerOpen"); - onItemEndReached = () => this.props.onEndReached("item"); onCategoryEndReached = () => this.props.onEndReached("category"); @@ -52,14 +50,15 @@ export default class SalesList extends React.PureComponent { return (
- + diff --git a/src/stories/screens/SalesReceipt/index.js b/src/stories/screens/SalesReceipt/index.js index e9d56c8..5d6cc97 100644 --- a/src/stories/screens/SalesReceipt/index.js +++ b/src/stories/screens/SalesReceipt/index.js @@ -29,6 +29,7 @@ class SalesReceipt extends React.Component { onCancelOrder, isViewingOrder, isCurrencyDisabled, + enableOverallTax, } = this.props; const totalPayment = receipt ? receipt.netTotal.toFixed(2) : "0.00"; return ( @@ -43,12 +44,19 @@ class SalesReceipt extends React.Component { /> diff --git a/src/utils.js b/src/utils.js index bdc3d28..24edf40 100644 --- a/src/utils.js +++ b/src/utils.js @@ -35,6 +35,7 @@ export const createReceiptLine = (item, category) => { category: category, item_name: item.description, price: parseFloat(item.price), + tax: parseFloat(item.tax), qty: 1, }); }; From 4b495e321c2b12f074b7d8da82c85d002e2ac84b Mon Sep 17 00:00:00 2001 From: jiloysss Date: Wed, 6 Nov 2019 09:54:15 +0800 Subject: [PATCH 08/29] NFC Feature --- android/app/build.gradle | 2 + android/app/src/main/AndroidManifest.xml | 18 +- .../main/java/com/tailpos/MainActivity.java | 19 +- .../java/com/tailpos/MainApplication.java | 4 + .../app/src/main/res/xml/nfc_tech_filter.xml | 29 + android/settings.gradle | 4 + android/src/main/res/xml/nfc_tech_filter.xml | 29 + ios/TailPOS.xcodeproj/project.pbxproj | 19 + package-lock.json | 50 +- package.json | 2 + src/boot/background_job.js | 18 + src/boot/configureStore.js | 3 - src/boot/setup.js | 18 +- src/container/PaymentContainer/controller.js | 12 +- src/container/PaymentContainer/index.js | 984 +----------------- .../nfc_manager_initialization.js | 111 ++ src/container/PaymentContainer/on_pay.js | 912 ++++++++++++++++ src/container/SalesContainer/index.js | 10 +- src/container/SettingsContainer/index.js | 5 + src/store/PosStore/DbFunctions.js | 33 +- src/store/PosStore/PaymentStore.js | 2 +- src/store/PosStore/ReceiptStore.js | 6 +- src/store/PosStore/WalletStore.js | 103 -- src/store/PosStore/syncInBackground.js | 28 +- src/store/StateStore/StateStore.js | 6 +- .../components/MoreSettingsComponent.js | 22 +- src/stories/components/NumberKeysComponent.js | 52 +- src/stories/screens/Payment/index.js | 13 +- src/stories/screens/Settings/index.js | 4 + 29 files changed, 1300 insertions(+), 1218 deletions(-) create mode 100644 android/app/src/main/res/xml/nfc_tech_filter.xml create mode 100644 android/src/main/res/xml/nfc_tech_filter.xml create mode 100644 src/boot/background_job.js create mode 100644 src/container/PaymentContainer/nfc_manager_initialization.js create mode 100644 src/container/PaymentContainer/on_pay.js delete mode 100644 src/store/PosStore/WalletStore.js diff --git a/android/app/build.gradle b/android/app/build.gradle index 6dd7daa..b57e3a6 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -177,6 +177,8 @@ android { } dependencies { + compile project(':react-native-nfc-manager') + compile project(':react-native-key-event') compile project(':react-native-localization') compile project(':react-native-background-job') compile project(':react-native-bluetooth-status') diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8babdb9..b06f030 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,7 +9,7 @@ - + + android:screenOrientation="landscape" + android:launchMode="singleTask"> + + + + + + + + + + + + + diff --git a/android/app/src/main/java/com/tailpos/MainActivity.java b/android/app/src/main/java/com/tailpos/MainActivity.java index 3489891..c2d3831 100644 --- a/android/app/src/main/java/com/tailpos/MainActivity.java +++ b/android/app/src/main/java/com/tailpos/MainActivity.java @@ -1,7 +1,8 @@ package com.tailpos; import android.os.Bundle; - +import android.view.KeyEvent; // <--- import +import net.kangyufei.KeyEventModule; // <--- import import org.devio.rn.splashscreen.SplashScreen; import com.facebook.react.ReactActivity; @@ -22,4 +23,20 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } + @Override // <--- Add this method if you want to react to keyDown + public boolean onKeyDown(int keyCode, KeyEvent event) { + + KeyEventModule.getInstance().onKeyDownEvent(keyCode, event); + super.onKeyDown(keyCode, event); + return true; + } + + @Override // <--- Add this method if you want to react to keyUp + public boolean onKeyUp(int keyCode, KeyEvent event) { + KeyEventModule.getInstance().onKeyUpEvent(keyCode, event); + + super.onKeyUp(keyCode, event); + return true; + } + } diff --git a/android/app/src/main/java/com/tailpos/MainApplication.java b/android/app/src/main/java/com/tailpos/MainApplication.java index 9e07ab7..0826b6c 100644 --- a/android/app/src/main/java/com/tailpos/MainApplication.java +++ b/android/app/src/main/java/com/tailpos/MainApplication.java @@ -4,6 +4,8 @@ import com.solinor.bluetoothstatus.RNBluetoothManagerPackage; import com.facebook.react.ReactApplication; +import community.revteltech.nfc.NfcManagerPackage; +import net.kangyufei.KeyEventPackage; import com.babisoft.ReactNativeLocalization.ReactNativeLocalizationPackage; import com.pilloxa.backgroundjob.BackgroundJobPackage; import com.learnium.RNDeviceInfo.RNDeviceInfo; @@ -37,6 +39,8 @@ protected List getPackages() { return Arrays.asList( new RNBluetoothManagerPackage(), new MainReactPackage(), + new NfcManagerPackage(), + new KeyEventPackage(), new ReactNativeLocalizationPackage(), new BackgroundJobPackage(), new RNDeviceInfo(), diff --git a/android/app/src/main/res/xml/nfc_tech_filter.xml b/android/app/src/main/res/xml/nfc_tech_filter.xml new file mode 100644 index 0000000..14c651f --- /dev/null +++ b/android/app/src/main/res/xml/nfc_tech_filter.xml @@ -0,0 +1,29 @@ + + + android.nfc.tech.IsoDep + + + android.nfc.tech.NfcA + + + android.nfc.tech.NfcB + + + android.nfc.tech.NfcF + + + android.nfc.tech.NfcV + + + android.nfc.tech.Ndef + + + android.nfc.tech.NdefFormatable + + + android.nfc.tech.MifareClassic + + + android.nfc.tech.MifareUltralight + + \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle index 8900f48..d465898 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,8 @@ rootProject.name = 'TailPOS' +include ':react-native-nfc-manager' +project(':react-native-nfc-manager').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-nfc-manager/android') +include ':react-native-key-event' +project(':react-native-key-event').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-key-event/android') include ':react-native-localization' project(':react-native-localization').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-localization/android') include ':react-native-background-job' diff --git a/android/src/main/res/xml/nfc_tech_filter.xml b/android/src/main/res/xml/nfc_tech_filter.xml new file mode 100644 index 0000000..14c651f --- /dev/null +++ b/android/src/main/res/xml/nfc_tech_filter.xml @@ -0,0 +1,29 @@ + + + android.nfc.tech.IsoDep + + + android.nfc.tech.NfcA + + + android.nfc.tech.NfcB + + + android.nfc.tech.NfcF + + + android.nfc.tech.NfcV + + + android.nfc.tech.Ndef + + + android.nfc.tech.NdefFormatable + + + android.nfc.tech.MifareClassic + + + android.nfc.tech.MifareUltralight + + \ No newline at end of file diff --git a/ios/TailPOS.xcodeproj/project.pbxproj b/ios/TailPOS.xcodeproj/project.pbxproj index 71ffce9..d83f712 100644 --- a/ios/TailPOS.xcodeproj/project.pbxproj +++ b/ios/TailPOS.xcodeproj/project.pbxproj @@ -66,6 +66,7 @@ 43FFBF74D0094DD8866DD727 /* libRNBluetoothManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 114C3F4566DC4AAFBF009FFF /* libRNBluetoothManager.a */; }; 51F0F7BBE5C142D4B8521808 /* libRNBackgroundJob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 030627CBACC14D929C0207BD /* libRNBackgroundJob.a */; }; 520D4F11F21A4CEEB05724EB /* libReactNativeLocalization.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A5548395195745ED8AFFDEBB /* libReactNativeLocalization.a */; }; + 6BEB5BDCB20043EA80E560C6 /* libNfcManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D806BF8811F4260B10899D2 /* libNfcManager.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -413,6 +414,8 @@ 030627CBACC14D929C0207BD /* libRNBackgroundJob.a */ = {isa = PBXFileReference; name = "libRNBackgroundJob.a"; path = "libRNBackgroundJob.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; D5BF8BC30E324943AB843FEB /* ReactNativeLocalization.xcodeproj */ = {isa = PBXFileReference; name = "ReactNativeLocalization.xcodeproj"; path = "../node_modules/react-native-localization/ReactNativeLocalization.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; A5548395195745ED8AFFDEBB /* libReactNativeLocalization.a */ = {isa = PBXFileReference; name = "libReactNativeLocalization.a"; path = "libReactNativeLocalization.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + 2C27E3CBAD07414F89BF7DAE /* NfcManager.xcodeproj */ = {isa = PBXFileReference; name = "NfcManager.xcodeproj"; path = "../node_modules/react-native-nfc-manager/ios/NfcManager.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + 2D806BF8811F4260B10899D2 /* libNfcManager.a */ = {isa = PBXFileReference; name = "libNfcManager.a"; path = "libNfcManager.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -455,6 +458,7 @@ 43FFBF74D0094DD8866DD727 /* libRNBluetoothManager.a in Frameworks */, 51F0F7BBE5C142D4B8521808 /* libRNBackgroundJob.a in Frameworks */, 520D4F11F21A4CEEB05724EB /* libReactNativeLocalization.a in Frameworks */, + 6BEB5BDCB20043EA80E560C6 /* libNfcManager.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -657,6 +661,7 @@ 0FC20227933C497CB2330EEF /* RNBluetoothManager.xcodeproj */, 2140AF7DBD7F486D8BC7E6D1 /* RNBackgroundJob.xcodeproj */, D5BF8BC30E324943AB843FEB /* ReactNativeLocalization.xcodeproj */, + 2C27E3CBAD07414F89BF7DAE /* NfcManager.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -1320,6 +1325,7 @@ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TailPOS.app/TailPOS"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1336,6 +1342,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Debug; @@ -1356,6 +1363,7 @@ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TailPOS.app/TailPOS"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1372,6 +1380,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Release; @@ -1406,6 +1415,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Debug; @@ -1439,6 +1449,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Release; @@ -1468,6 +1479,7 @@ TVOS_DEPLOYMENT_TARGET = 9.2; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1484,6 +1496,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Debug; @@ -1513,6 +1526,7 @@ TVOS_DEPLOYMENT_TARGET = 9.2; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1529,6 +1543,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Release; @@ -1557,6 +1572,7 @@ TVOS_DEPLOYMENT_TARGET = 10.1; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1573,6 +1589,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Debug; @@ -1601,6 +1618,7 @@ TVOS_DEPLOYMENT_TARGET = 10.1; LIBRARY_SEARCH_PATHS = ( "$(inherited)", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1617,6 +1635,7 @@ "$(SRCROOT)/../node_modules/react-native-bluetooth-status/ios", "$(SRCROOT)/../node_modules/react-native-background-job/ios", "$(SRCROOT)/../node_modules/react-native-localization", + "$(SRCROOT)/../node_modules/react-native-nfc-manager/ios", ); }; name = Release; diff --git a/package-lock.json b/package-lock.json index 79bba66..5c93029 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tailpos", - "version": "1.3.0", + "version": "1.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4329,8 +4329,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.1.1", @@ -4395,7 +4394,6 @@ "boom": { "version": "2.10.1", "bundled": true, - "optional": true, "requires": { "hoek": "2.x.x" } @@ -4538,13 +4536,11 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "fstream": { "version": "1.0.11", "bundled": true, - "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -4595,7 +4591,6 @@ "glob": { "version": "7.1.2", "bundled": true, - "optional": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4607,8 +4602,7 @@ }, "graceful-fs": { "version": "4.1.11", - "bundled": true, - "optional": true + "bundled": true }, "har-schema": { "version": "1.0.5", @@ -4642,8 +4636,7 @@ }, "hoek": { "version": "2.16.3", - "bundled": true, - "optional": true + "bundled": true }, "http-signature": { "version": "1.1.1", @@ -4658,7 +4651,6 @@ "inflight": { "version": "1.0.6", "bundled": true, - "optional": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -4666,8 +4658,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.4", @@ -4767,7 +4758,6 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "1.1.7" } @@ -4780,7 +4770,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -4813,8 +4802,8 @@ "bundled": true, "optional": true, "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npmlog": { @@ -4846,7 +4835,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -4866,14 +4854,13 @@ "bundled": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "performance-now": { "version": "0.2.0", @@ -4959,7 +4946,6 @@ "rimraf": { "version": "2.6.1", "bundled": true, - "optional": true, "requires": { "glob": "^7.0.5" } @@ -5041,7 +5027,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5130,8 +5115,7 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -10082,6 +10066,11 @@ "resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.0.2.tgz", "integrity": "sha512-5FYNC4kTi/YK86l+r8GQ0xgsSL2tleCQ5Yppu1+ARbnm2qGRmDoJTGSNsWBAWa8FP1ORyhMjxi18IlvSRKaI2g==" }, + "react-native-key-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-native-key-event/-/react-native-key-event-1.0.0.tgz", + "integrity": "sha512-bb57EC7q9Y+YUS29Z461neSZlMYKq92x1J1zOd+TdE9Sos3Iqz+c1AwCpng1ob4nR2FUwqI+QAQ3j57rHF5dRQ==" + }, "react-native-keyboard-aware-scroll-view": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.5.0.tgz", @@ -10156,6 +10145,11 @@ "react-native-animatable": "^1.2.4" } }, + "react-native-nfc-manager": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/react-native-nfc-manager/-/react-native-nfc-manager-1.2.2.tgz", + "integrity": "sha512-mOJD2YDpPaG+JzsjB03c+xDsRHr2Vm5CFRr9rtMRt+c/9jdvn/c2+VXCFA5/PJ1GEXdY/vFFOP96Qv5kAau8Mw==" + }, "react-native-orientation": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/react-native-orientation/-/react-native-orientation-3.1.3.tgz", diff --git a/package.json b/package.json index cdd7fea..d8457ce 100644 --- a/package.json +++ b/package.json @@ -87,9 +87,11 @@ "react-native-datepicker": "^1.7.2", "react-native-device-info": "^0.21.5", "react-native-frappe-fetch": "^0.9.1", + "react-native-key-event": "^1.0.0", "react-native-localization": "^2.1.2", "react-native-maps": "^0.21.0", "react-native-modal": "^6.0.0", + "react-native-nfc-manager": "^1.2.2", "react-native-orientation": "^3.1.3", "react-native-searchable-dropdown": "^1.0.4", "react-native-simple-dialogs": "^0.3.1", diff --git a/src/boot/background_job.js b/src/boot/background_job.js new file mode 100644 index 0000000..4e7fdb5 --- /dev/null +++ b/src/boot/background_job.js @@ -0,0 +1,18 @@ +import BackgroundJob from "react-native-background-job"; +import { syncObjectValues } from "../store/PosStore/syncInBackground"; + +export function background_job_initialization(stores2) { + BackgroundJob.cancel({ jobKey: "AutomaticSync" }); + const backgroundJob = { + jobKey: "myJob", + job: () => syncObjectValues("sync", stores2, true), + }; + BackgroundJob.register(backgroundJob); + let backgroundSchedule = { + jobKey: "myJob", + period: 360000, + allowExecutionInForeground: true, + networkType: BackgroundJob.NETWORK_TYPE_UNMETERED, + }; + BackgroundJob.schedule(backgroundSchedule); +} diff --git a/src/boot/configureStore.js b/src/boot/configureStore.js index 96decce..af6d28b 100644 --- a/src/boot/configureStore.js +++ b/src/boot/configureStore.js @@ -11,7 +11,6 @@ import ShiftStore from "@posStore/ShiftStore"; import TaxesStore from "@posStore/TaxesStore"; import SyncStore from "@posStore/SyncStore"; import RoleStore from "@posStore/RoleStore"; -import WalletStore from "@posStore/WalletStore"; import ShiftReportsStore from "@posStore/ShiftReportsStore"; import LoginStore from "@viewStore/LoginViewStore"; import SignupStore from "@viewStore/SignupViewStore"; @@ -35,7 +34,6 @@ export default function() { const shiftStore = ShiftStore; const syncStore = SyncStore; const signupForm = SignupStore; - const walletStore = WalletStore; const roleStore = RoleStore; const shiftReportsStore = ShiftReportsStore; const lostPasswordForm = LostPasswordStore; @@ -61,6 +59,5 @@ export default function() { stateStore, headSyncStore, roleStore, - walletStore, }; } diff --git a/src/boot/setup.js b/src/boot/setup.js index 8c3c2e8..890b187 100755 --- a/src/boot/setup.js +++ b/src/boot/setup.js @@ -2,29 +2,15 @@ import * as React from "react"; import { Provider } from "mobx-react/native"; import { StyleProvider } from "native-base"; import Orientation from "react-native-orientation"; -import BackgroundJob from "react-native-background-job"; import config from "./configureStore"; -import { syncObjectValues } from "../store/PosStore/syncInBackground"; +import { background_job_initialization } from "./background_job"; import App from "../App"; import getTheme from "../theme/components"; import variables from "../theme/variables/platform"; const stores2 = config(); -BackgroundJob.cancel({ jobKey: "AutomaticSync" }); -const backgroundJob = { - jobKey: "myJob", - job: () => syncObjectValues("sync", stores2, true), -}; -BackgroundJob.register(backgroundJob); -var backgroundSchedule = { - jobKey: "myJob", - period: 360000, - allowExecutionInForeground: true, - networkType: BackgroundJob.NETWORK_TYPE_UNMETERED, -}; -BackgroundJob.schedule(backgroundSchedule); - +background_job_initialization(stores2); export default function(stores) { return class Setup extends React.Component { constructor(props) { diff --git a/src/container/PaymentContainer/controller.js b/src/container/PaymentContainer/controller.js index e0dee45..a4c5036 100644 --- a/src/container/PaymentContainer/controller.js +++ b/src/container/PaymentContainer/controller.js @@ -1,3 +1,4 @@ +import { nfc_initialization, unregister_tag_event } from "./nfc_manager_initialization"; export default class PaymentController { constructor(stateStore) { this.stateStore = stateStore; @@ -5,9 +6,18 @@ export default class PaymentController { modalVisibleChange = modalVisible => { this.stateStore.changeValue("modalVisible", modalVisible, "Payment"); }; - onChangePayment = payment => { + onChangePayment = (payment, props) => { this.stateStore.changeValue("selected", payment, "Payment"); + if (payment === "Wallet") { + this.stateStore.setPaymentValue(this.stateStore.amount_due); + nfc_initialization(props,this.stateStore.deviceId); + + } else { + this.stateStore.setPaymentValue("0"); + unregister_tag_event(); + } }; + onChangeCustomerName = customerName => { this.stateStore.changeValue("customerName", customerName, "Payment"); }; diff --git a/src/container/PaymentContainer/index.js b/src/container/PaymentContainer/index.js index 343f2a2..0eb5d7c 100644 --- a/src/container/PaymentContainer/index.js +++ b/src/container/PaymentContainer/index.js @@ -3,21 +3,17 @@ import { Alert } from "react-native"; import { Toast } from "native-base"; import BluetoothSerial from "react-native-bluetooth-serial"; import { BluetoothStatus } from "react-native-bluetooth-status"; -import TinyPOS from "tiny-esc-pos"; -import { formatNumber } from "accounting-js"; import * as EmailValidator from "email-validator"; import { inject, observer } from "mobx-react/native"; import { currentLanguage } from "../../translations/CurrentLanguage"; import PaymentController from "./controller"; import PaymentScreen from "@screens/Payment"; - +import { on_pay } from "./on_pay"; import translation from "../../translations/translation"; import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); -const moment = require("moment"); - @inject( "itemStore", "customerStore", @@ -143,963 +139,12 @@ export default class PaymentContainer extends React.Component { } }; - setOrderCompleted() { - const { - queueOrigin, - currentTable, - setCurrentTable, - } = this.props.stateStore; - - const url = `${queueOrigin}/api/v1/complete_order`; - const fetchData = { - method: "POST", - body: JSON.stringify({ - id: currentTable, - }), - }; - - fetch(url, fetchData) - .then(res => res.json()) - .then(res => setCurrentTable(-1)); - } onPay = async () => { - const paymentValue = parseFloat(this.props.stateStore.payment_value); - const amountDue = parseFloat(this.props.stateStore.amount_due); - - if (paymentValue < amountDue) { - Alert.alert( - strings.Alert, - strings.AmountPaidMustBeGreaterThanOrEqualToAmountDue, - ); - } else if (paymentValue >= amountDue) { - let receiptNumber = await this.props.receiptStore.numberOfReceipts(); - let receiptNumberLength = receiptNumber.toString().length; - let finalReceiptNumber = ""; - for ( - let lengthNumber = 0; - lengthNumber < 15 - receiptNumberLength; - lengthNumber += 1 - ) { - finalReceiptNumber = finalReceiptNumber + "0"; - } - finalReceiptNumber = finalReceiptNumber + receiptNumber.toString(); - - const receiptCurrent = this.props.receiptStore.defaultReceipt; - const { deviceId } = this.props.stateStore; - - if (deviceId) { - receiptCurrent.setDeviceId(deviceId); - } - - BluetoothSerial.isConnected().then(res => { - let totalPurchase = 0.0; - Alert.alert( - strings.ReceiptConfirmation, // title - strings.DoYouWantToPrintReceipt, - [ - { - text: strings.No, - style: "cancel", - onPress: () => { - this.setOrderCompleted(); - this.props.shiftStore.defaultShift.addTotalDiscount( - receiptCurrent.discounts, - ); - this.props.shiftStore.defaultShift.addTotalTaxes( - parseFloat(this.props.receiptStore.defaultReceipt.subtotal) * - (parseFloat(receiptCurrent.taxesValue) / 100), - ); - this.props.shiftStore.defaultShift.addNumberOfTransaction(); - - let totalAmountDue = 0.0; - - this.props.receiptStore.defaultReceipt.lines.map(val => { - totalAmountDue = - parseInt(totalAmountDue, 10) + - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10); - if (val.category && val.category !== "No Category") { - this.props.shiftStore.defaultShift.categoriesAmounts({ - name: val.category, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - if (this.props.stateStore.payment_state[0].selected) { - this.props.shiftStore.defaultShift.mopAmounts({ - name: this.props.stateStore.payment_state[0].selected, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - }); - if ( - this.props.receiptStore.defaultReceipt.orderType !== "None" - ) { - this.props.shiftStore.defaultShift.addOrderType({ - amount: parseFloat(totalAmountDue, 10), - type: this.props.receiptStore.defaultReceipt.orderType, - }); - } - this.props.shiftStore.defaultShift.addTotalSales( - totalAmountDue, - ); - this.props.receiptStore.defaultReceipt.lines.map(val => { - totalPurchase = - parseFloat(totalPurchase, 10) + - parseFloat(val.price, 10) * parseFloat(val.qty, 10); - }); - - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - const { defaultShift } = this.props.shiftStore; - - // If shift started and shift hasn't ended - if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { - // Set the default receipt - const { defaultReceipt } = this.props.receiptStore; - - // set shift - defaultReceipt.setShift(defaultShift._id); - - const { ending_cash } = defaultShift; - - // Set the end cash - defaultShift.setEndCash( - ending_cash + defaultReceipt.netTotal, - ); - } - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.stateStore.enableOverallTax - ? this.props.receiptStore.defaultReceipt.get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - - // this.props.receiptStore.defaultReceipt.clear(); - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - this.props.receiptStore.add( - this.props.receiptStore.defaultReceipt, - ); - this.props.receiptStore.setPreviousReceipt( - this.props.receiptStore.defaultReceipt, - ); - let discountValueForDisplay = this.props.receiptStore - .defaultReceipt.discounts; - let taxesValueForDisplay = this.props.stateStore - .enableOverallTax - ? this.props.receiptStore.defaultReceipt.get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item; - this.props.receiptStore.newReceipt( - this.props.printerStore.companySettings[0].tax, - ); - this.props.receiptStore.setLastScannedBarcode(""); - this.props.receiptStore.unselectReceiptLine(); - this.props.navigation.navigate("Sales", { - cash: this.props.stateStore.payment_value, - change: parseFloat( - parseFloat(this.props.stateStore.payment_value, 10) - - (parseFloat(totalPurchase, 10) - - parseFloat(discountValueForDisplay, 10) + - parseFloat(taxesValueForDisplay, 10)), - 10, - ), - }); - }, - }, - { - text: strings.Yes, - onPress: () => { - this.setOrderCompleted(); - this.props.shiftStore.defaultShift.addTotalDiscount( - receiptCurrent.discounts, - ); - this.props.shiftStore.defaultShift.addTotalTaxes( - parseFloat(this.props.receiptStore.defaultReceipt.subtotal) * - (parseFloat(receiptCurrent.taxesValue) / 100), - ); - this.props.shiftStore.defaultShift.addNumberOfTransaction(); - - // Let me print first - let totalAmountDue = 0.0; - let commission_toto = 0.0; - this.props.receiptStore.defaultReceipt.lines.map(val => { - // const { defaultShift } = this.props.shiftStore; - let ComHolder = JSON.parse(val.commission_details); - ComHolder.map(val2 => { - commission_toto = - commission_toto + parseInt(val2.commission_amount, 10); - }); - // defaultShift.addCommission( - // parseInt(val.commission_amount, 10), - // ); - totalAmountDue = - parseInt(totalAmountDue, 10) + - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10); - if (val.category && val.category !== "No Category") { - this.props.shiftStore.defaultShift.categoriesAmounts({ - name: val.category, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - if (this.props.stateStore.payment_state[0].selected) { - this.props.shiftStore.defaultShift.mopAmounts({ - name: this.props.stateStore.payment_state[0].selected, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - }); - if ( - this.props.receiptStore.defaultReceipt.orderType !== "None" - ) { - this.props.shiftStore.defaultShift.addOrderType({ - amount: parseFloat(totalAmountDue, 10), - type: this.props.receiptStore.defaultReceipt.orderType, - }); - } - this.props.shiftStore.defaultShift.addTotalSales( - totalAmountDue, - ); - if (res) { - let writePromises = []; - - for ( - let printedReceipts = 0; - printedReceipts < - parseInt( - this.props.printerStore.companySettings[0] - .changeNoReceipts, - 10, - ); - printedReceipts += 1 - ) { - writePromises = []; - - writePromises.push(BluetoothSerial.write(TinyPOS.init())); - - // Header - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].name - ? this.props.printerStore.companySettings[0].name.toString() - : "" - : "" - }`, - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].header.toString() - : "" - }`, - { align: "center", size: "normal" }, - true, - ), - ), - ); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - - // Date - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, - { size: "normal" }, - true, - ), - ), - ); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Cashier + - `${ - this.props.attendantStore.defaultAttendant - .user_name - }`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.TransactionNo + `${finalReceiptNumber}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "Mode of payment: " + - this.props.stateStore.payment_state[0].selected, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Purchases, - { align: "center", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Items + - " " + - strings.Amount + - " ", - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - - this.props.receiptStore.defaultReceipt.lines.map(val => { - let finalLines = ""; - - const name = val.item_name; - - if (name.length > 14) { - let quotientValue = name.length / 14; - for ( - let quotient = 0; - quotient < parseInt(quotientValue, 10); - quotient += 1 - ) { - let currentCounter = quotient * 14; - let nameCounter = ""; - for ( - let n = currentCounter; - n < (quotient + 1) * 14; - n += 1 - ) { - nameCounter = nameCounter + name[n]; - } - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${nameCounter}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - } - if ( - name.length - parseInt(quotientValue, 10) * 14 > - 0 - ) { - let nameCounterOverflow = ""; - for ( - let m = parseInt(quotientValue, 10) * 14; - m < name.length; - m += 1 - ) { - nameCounterOverflow = nameCounterOverflow + name[m]; - } - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${nameCounterOverflow}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - } - } else { - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${name}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - } - - let priceString = formatNumber( - parseFloat(val.price, 10), - ).toString(); - let qtyString = val.qty.toString(); - let amountString = formatNumber( - parseFloat(val.price, 10) * parseFloat(val.qty, 10), - ).toString(); - - for (let ps = 0; ps < 12 - priceString.length; ps += 1) { - finalLines = finalLines + " "; - } - - finalLines = finalLines + priceString; - - for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { - finalLines = finalLines + " "; - } - finalLines = finalLines + qtyString; - - for (let as = 0; as < 14 - amountString.length; as += 1) { - finalLines = finalLines + " "; - } - - finalLines = finalLines + amountString; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${finalLines}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - if (printedReceipts === 0) { - totalPurchase = - parseFloat(totalPurchase, 10) + - parseFloat(val.price, 10) * parseFloat(val.qty, 10); - } - }); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - - let subTotal = strings.Subtotal; - let sub = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.subtotal, - 10, - ), - ).toString(); - for (let t = 0; t < 23 - sub.length; t += 1) { - subTotal = subTotal + " "; - } - subTotal = subTotal + sub; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${subTotal}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - let taxValue = strings.Tax; - let tax = formatNumber( - parseFloat( - this.props.stateStore.enableOverallTax - ? this.props.receiptStore.defaultReceipt.get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - 10, - ), - ).toString(); - for (let t = 0; t < 29 - tax.length; t += 1) { - taxValue = taxValue + " "; - } - taxValue = taxValue + tax; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${taxValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - let discountValue = strings.Discount; - let discount = formatNumber( - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, - ), - ).toString(); - for (let d = 0; d < 24 - discount.length; d += 1) { - discountValue = discountValue + " "; - } - discountValue = discountValue + discount; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${discountValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - - let commissionValue = strings.Commission; - - let commission_total = formatNumber( - parseFloat(commission_toto, 10), - ).toString(); - for (let d = 0; d < 22 - commission_total.length; d += 1) { - commissionValue = commissionValue + " "; - } - commissionValue = commissionValue + commission_total; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${commissionValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - - let total = ""; - total = total + strings.TotalAmount; - - for ( - let totalLength = 0; - totalLength < - 20 - - formatNumber(parseFloat(totalPurchase, 10)).toString() - .length; - totalLength += 1 - ) { - total = total + " "; - } - total = - total + - formatNumber( - parseFloat(totalPurchase, 10) - - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, - ) + - parseFloat( - this.props.stateStore.enableOverallTax - ? this.props.receiptStore.defaultReceipt - .get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - 10, - ), - ).toString(); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${total}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - let cash = strings.Cash; - for ( - let cashLength = 0; - cashLength < - 28 - - formatNumber( - parseFloat(this.props.stateStore.payment_value, 10), - ).toString().length; - cashLength += 1 - ) { - cash = cash + " "; - } - cash = - cash + - formatNumber( - parseFloat(this.props.stateStore.payment_value, 10), - ).toString(); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${cash}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - let change = strings.Change; - let changeValue = formatNumber( - parseFloat( - parseFloat(this.props.stateStore.payment_value, 10) - - (parseFloat(totalPurchase, 10) - - parseFloat( - this.props.receiptStore.defaultReceipt.discounts, - 10, - ) + - parseFloat( - this.props.stateStore.enableOverallTax - ? this.props.receiptStore.defaultReceipt - .get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - 10, - )), - 10, - ), - ).toString(); - for ( - let changeLength = 0; - changeLength < 26 - changeValue.length; - changeLength += 1 - ) { - change = change + " "; - } - change = change + changeValue; - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${change}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.ThisServesAsYour, - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.OfficialReceipt + "\n", - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - this.props.printerStore.companySettings.length > 0 - ? this.props.printerStore.companySettings[0].footer.toString() - : "" - }`, - { align: "center", size: "normal" }, - true, - ), - ), - ); - // writePromises.push( - // BluetoothSerial.write( - // TinyPOS.bufferedText( - // "\n" + - // strings.POSProvider + - // "Bai Web and Mobile Lab\n" + - // "Insular Life Bldg, Don Apolinar\n" + - // "Velez cor. Oldarico Akut St.,\n" + - // "Cagayan de Oro, 9000,\n" + - // "Misamis Oriental\n" + - // strings.AccredNo + - // strings.DateIssued + - // strings.ValidUntil, - // { align: "left", size: "normal" }, - // true, - // ), - // ), - // ); - // writePromises.push( - // BluetoothSerial.write( - // TinyPOS.bufferedText( - // strings.ThisReceiptShallBeValidFor + - // strings.FiveYearsFromTheDateOf + - // strings.ThePermitToUse, - // { align: "center", size: "normal" }, - // true, - // ), - // ), - // ); - - // Add 3 new lines - writePromises.push( - BluetoothSerial.write(TinyPOS.bufferedLine(3)), - ); - } - // Push drawer - writePromises.push( - BluetoothSerial.write(TinyPOS.kickCashDrawer()), - ); - writePromises.push( - BluetoothSerial.write(TinyPOS.kickCashDrawer()), - ); - Promise.all(writePromises) - .then(res2 => { - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.stateStore.enableOverallTax - ? this.props.receiptStore.defaultReceipt.get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - // add to row - - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - - // Reset payment amount - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - this.props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - this.props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - - Toast.show({ - text: strings.TransactionCompleted, - duration: 5000, - }); - }) - .catch(err => { - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.stateStore.enableOverallTax - ? this.props.receiptStore.defaultReceipt.get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - - // add to row - - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - this.props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - this.props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - - Toast.show({ - text: err.message + strings.TransactionCompleted, - buttonText: strings.Okay, - position: "bottom", - duration: 5000, - }); - }); - } else { - receiptCurrent.completed( - this.props.attendantStore.defaultAttendant.user_name, - ); - - this.props.receiptStore.defaultReceipt.changeTaxesAmount( - this.props.stateStore.enableOverallTax - ? this.props.receiptStore.defaultReceipt.get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - - // add to row - this.props.paymentStore.add({ - receipt: this.props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt(this.props.stateStore.payment_value, 10), - type: this.props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, - }); - - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - this.props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - this.props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - Toast.show({ - text: - strings.TransactionCompleted[ - strings.UnableToConnectPrinter - ], - buttonText: strings.Okay, - position: "bottom", - duration: 6000, - }); - } - - const { defaultShift } = this.props.shiftStore; - - // If shift started and shift hasn't ended - if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { - // Set the default receipt - const { defaultReceipt } = this.props.receiptStore; - - // set shift - defaultReceipt.setShift(defaultShift._id); - - const { ending_cash } = defaultShift; - - // Set the end cash - defaultShift.setEndCash( - ending_cash + defaultReceipt.netTotal, - ); - } - - // this.props.receiptStore.defaultReceipt.clear(); - this.props.receiptStore.add( - this.props.receiptStore.defaultReceipt, - ); - this.props.receiptStore.setPreviousReceipt( - this.props.receiptStore.defaultReceipt, - ); - let discountValueForDisplay = this.props.receiptStore - .defaultReceipt.discounts; - let taxesValueForDisplay = this.props.stateStore - .enableOverallTax - ? this.props.receiptStore.defaultReceipt.get_tax_total - : this.props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item; - this.props.receiptStore.newReceipt( - this.props.printerStore.companySettings[0].tax, - ); - this.props.receiptStore.setLastScannedBarcode(""); - this.props.receiptStore.unselectReceiptLine(); - this.props.navigation.navigate("Sales", { - cash: this.props.stateStore.payment_value, - change: parseFloat( - parseFloat(this.props.stateStore.payment_value, 10) - - (parseFloat(totalPurchase, 10) - - parseFloat(discountValueForDisplay, 10) + - parseFloat(taxesValueForDisplay, 10)), - 10, - ), - }); - }, - }, - ], - ); - }); - } + const { defaultReceipt } = this.props.receiptStore; + const { defaultAttendant } = this.props.attendantStore; + defaultReceipt.setAttendant(defaultAttendant.user_name); + on_pay(this.props); }; onBack() { @@ -1110,19 +155,6 @@ export default class PaymentContainer extends React.Component { this.getBluetoothState(true); this.onBack(); }; - // DEPRECATED - // onPrinterChange(value) { - // this.props.stateStore.changeValue("itemSelected", value, "Payment"); - // BluetoothSerial.connect("DC:0D:30:0B:77:B1") - // .then(res => { - // this.props.stateStore.changeValue("connection", true, "Payment"); - // }) - // .catch(() => { - // // this.setState({ connection: false }); - // this.props.stateStore.changeValue("connection", false, "Payment"); - // }); - // } - onPrinterPress = () => { this.props.navigation.navigate("Settings"); }; @@ -1253,9 +285,6 @@ export default class PaymentContainer extends React.Component { this.props.stateStore.changeValue("customerPhoneNumber", "", "Payment"); this.props.stateStore.changeValue("customerNotes", "", "Payment"); }; - onChangeCardNumber = text => { - this.props.stateStore.changeValue("walletCardNumber", text, "Payment"); - }; render() { strings.setLanguage(currentLanguage().companyLanguage); return ( @@ -1277,7 +306,7 @@ export default class PaymentContainer extends React.Component { modalVisibleChange={this.controller.modalVisibleChange} navigation={this.navigation} onPrinterPress={this.onPrinterPress} - onChangePayment={this.controller.onChangePayment} + onChangePayment={(payment) => this.controller.onChangePayment(payment,this.props)} onChangeCustomerName={this.controller.onChangeCustomerName} onChangeCustomerEmail={this.controller.onChangeCustomerEmail} onChangeCustomerPhoneNumber={this.onChangeCustomerPhoneNumber} @@ -1291,7 +320,6 @@ export default class PaymentContainer extends React.Component { } useDefaultCustomer={this.props.stateStore.useDefaultCustomer} isCurrencyDisabled={this.props.stateStore.isCurrencyDisabled} - onChangeCardNumber={this.onChangeCardNumber} /> ); } diff --git a/src/container/PaymentContainer/nfc_manager_initialization.js b/src/container/PaymentContainer/nfc_manager_initialization.js new file mode 100644 index 0000000..02bdab8 --- /dev/null +++ b/src/container/PaymentContainer/nfc_manager_initialization.js @@ -0,0 +1,111 @@ +import NfcManager from "react-native-nfc-manager"; +import { showToastDanger } from "../../utils"; +import config from "../../boot/configureStore"; +import { on_pay } from "./on_pay"; + +import FrappeFetch from "react-native-frappe-fetch"; +let validUrl = require("valid-url"); +const stores = config(); + +export function nfc_initialization(props,deviceId) { + NfcManager.isSupported() + .then((result) => { + + if (result) { + check_tagged_nfc_card(props,deviceId); + + } else { + showToastDanger("Device does not support NFC"); + + } + + }); +} + +export function check_tagged_nfc_card(props,deviceId) { + NfcManager.isEnabled() + .then(status => { + if (status){ + register_tag_event(props,deviceId); + } else { + showToastDanger("NFC is disabled"); + }}); +} + +export function register_tag_event(props,deviceId) { + const nfc_props = {invalidateAfterFirstRead: true, isReaderModeEnabled: true}; + const message = "Scanning NFC Card"; + NfcManager.registerTagEvent(tag => validate_tag_event(tag,props,deviceId), message, nfc_props); +} + + +export function unregister_tag_event() { + NfcManager.unregisterTagEvent(); +} +export function set_attendant(props) { + const { defaultReceipt } = props.receiptStore; + const { defaultAttendant } = props.attendantStore; + defaultReceipt.setAttendant(defaultAttendant.user_name); +} +export async function validate_tag_event(tag, props,deviceId) { + set_attendant(props); + on_sync_tag_event(tag, props,deviceId); +} + +export async function on_sync_tag_event(tag, props,deviceId) { + if (tag){ + const { url, user_name, password } = stores.printerStore.sync[0]; + const { defaultReceipt } = stores.receiptStore; + const protocol = stores.stateStore.isHttps ? "https://" : "http://"; + let site_url = protocol + url; + + const site_info = { + url: site_url.toLowerCase(), + username: user_name, + password: password, + }; + if (validUrl.isWebUri(site_url.toLowerCase())) { + FrappeFetch.createClient(site_info).then(() => { + const { Client } = FrappeFetch; + return Client.postApi( + "tailpos_sync.wallet_sync.validate_customer_wallet", + { + wallet: tag.id, + receipt: json_object(defaultReceipt), + device_id: deviceId + }, + ); + }) + + .catch(() => {}) + .then(response => response.json()) + .then(responseJson => { + validate_return_from_server(responseJson.message, props); + }); + } else { + showToastDanger("Invalid URL. Please set valid URL in Sync Settings"); + } + + } + +} + +export function validate_return_from_server(data, props){ + if (data.failed) { + showToastDanger(data.message); + } else { + stores.navigation = props.navigation; + on_pay(stores); + } +} +export function json_object(obj){ + let receipt_json_object = {}; + Object.keys(obj).forEach(function(key) { + if (!(key === "_id")) { + receipt_json_object[key] = obj[key]; + } + }); + + + return receipt_json_object; +} diff --git a/src/container/PaymentContainer/on_pay.js b/src/container/PaymentContainer/on_pay.js new file mode 100644 index 0000000..25b8a6d --- /dev/null +++ b/src/container/PaymentContainer/on_pay.js @@ -0,0 +1,912 @@ +import { Alert } from "react-native"; +import TinyPOS from "tiny-esc-pos"; +import { formatNumber } from "accounting-js"; +import BluetoothSerial from "react-native-bluetooth-serial"; +import { Toast } from "native-base"; +import translation from "../../translations/translation"; +import LocalizedStrings from "react-native-localization"; +let strings = new LocalizedStrings(translation); +const moment = require("moment"); + +export async function setOrderCompleted(props) { + const { + queueOrigin, + currentTable, + setCurrentTable, + } = props.stateStore; + + const url = `${queueOrigin}/api/v1/complete_order`; + const fetchData = { + method: "POST", + body: JSON.stringify({ + id: currentTable, + }), + }; + + fetch(url, fetchData) + .then(res => res.json()) + .then(res => setCurrentTable(-1)); +} +export async function on_pay(props) { + const paymentValue = parseFloat(props.stateStore.payment_value); + const amountDue = parseFloat(props.stateStore.amount_due); + + if (paymentValue < amountDue) { + Alert.alert( + strings.Alert, + strings.AmountPaidMustBeGreaterThanOrEqualToAmountDue, + ); + } else if (paymentValue >= amountDue) { + let receiptNumber = await props.receiptStore.numberOfReceipts(); + let receiptNumberLength = receiptNumber.toString().length; + let finalReceiptNumber = ""; + for ( + let lengthNumber = 0; + lengthNumber < 15 - receiptNumberLength; + lengthNumber += 1 + ) { + finalReceiptNumber = finalReceiptNumber + "0"; + } + finalReceiptNumber = finalReceiptNumber + receiptNumber.toString(); + + const receiptCurrent = props.receiptStore.defaultReceipt; + const { deviceId } = props.stateStore; + + if (deviceId) { + receiptCurrent.setDeviceId(deviceId); + } + + BluetoothSerial.isConnected().then(res => { + let totalPurchase = 0.0; + Alert.alert( + strings.ReceiptConfirmation, // title + strings.DoYouWantToPrintReceipt, + [ + { + text: strings.No, + style: "cancel", + onPress: () => { + setOrderCompleted(props); + props.shiftStore.defaultShift.addTotalDiscount( + receiptCurrent.discounts, + ); + props.shiftStore.defaultShift.addTotalTaxes( + parseFloat(props.receiptStore.defaultReceipt.subtotal) * + (parseFloat(receiptCurrent.taxesValue) / 100), + ); + props.shiftStore.defaultShift.addNumberOfTransaction(); + + let totalAmountDue = 0.0; + + props.receiptStore.defaultReceipt.lines.map(val => { + totalAmountDue = + parseInt(totalAmountDue, 10) + + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10); + if (val.category && val.category !== "No Category") { + props.shiftStore.defaultShift.categoriesAmounts({ + name: val.category, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + if ( props.stateStore.payment_state[0].selected) { + props.shiftStore.defaultShift.mopAmounts({ + name: props.stateStore.payment_state[0].selected, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + }); + if ( + props.receiptStore.defaultReceipt.orderType !== "None" + ) { + props.shiftStore.defaultShift.addOrderType({ + amount: parseFloat(totalAmountDue, 10), + type: props.receiptStore.defaultReceipt.orderType, + }); + } + props.shiftStore.defaultShift.addTotalSales( + totalAmountDue, + ); + props.receiptStore.defaultReceipt.lines.map(val => { + totalPurchase = + parseFloat(totalPurchase, 10) + + parseFloat(val.price, 10) * parseFloat(val.qty, 10); + }); + + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + const { defaultShift } = props.shiftStore; + + // If shift started and shift hasn't ended + if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { + // Set the default receipt + const { defaultReceipt } = props.receiptStore; + + // set shift + defaultReceipt.setShift(defaultShift._id); + + const { ending_cash } = defaultShift; + + // Set the end cash + defaultShift.setEndCash( + ending_cash + defaultReceipt.netTotal, + ); + } + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + + // props.receiptStore.defaultReceipt.clear(); + payment_add(props); + + props.receiptStore.add( + props.receiptStore.defaultReceipt, + ); + props.receiptStore.setPreviousReceipt( + props.receiptStore.defaultReceipt, + ); + let discountValueForDisplay = props.receiptStore + .defaultReceipt.discounts; + let taxesValueForDisplay = props.stateStore + .enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item; + props.receiptStore.newReceipt( + props.printerStore.companySettings[0].tax, + ); + props.receiptStore.setLastScannedBarcode(""); + props.receiptStore.unselectReceiptLine(); + props.stateStore.changeValue("selected", "Cash", "Payment"); + change_navigation(props,totalPurchase, discountValueForDisplay,taxesValueForDisplay); + + }, + }, + { + text: strings.Yes, + onPress: () => { + setOrderCompleted(props); + props.shiftStore.defaultShift.addTotalDiscount( + receiptCurrent.discounts, + ); + props.shiftStore.defaultShift.addTotalTaxes( + parseFloat( props.receiptStore.defaultReceipt.subtotal) * + (parseFloat(receiptCurrent.taxesValue) / 100), + ); + props.shiftStore.defaultShift.addNumberOfTransaction(); + + // Let me print first + let totalAmountDue = 0.0; + let commission_toto = 0.0; + props.receiptStore.defaultReceipt.lines.map(val => { + // const { defaultShift } = props.shiftStore; + let ComHolder = JSON.parse(val.commission_details); + ComHolder.map(val2 => { + commission_toto = + commission_toto + parseInt(val2.commission_amount, 10); + }); + // defaultShift.addCommission( + // parseInt(val.commission_amount, 10), + // ); + totalAmountDue = + parseInt(totalAmountDue, 10) + + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10); + if (val.category && val.category !== "No Category") { + props.shiftStore.defaultShift.categoriesAmounts({ + name: val.category, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + if ( props.stateStore.payment_state[0].selected) { + props.shiftStore.defaultShift.mopAmounts({ + name: props.stateStore.payment_state[0].selected, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + }); + if ( + props.receiptStore.defaultReceipt.orderType !== "None" + ) { + props.shiftStore.defaultShift.addOrderType({ + amount: parseFloat(totalAmountDue, 10), + type: props.receiptStore.defaultReceipt.orderType, + }); + } + props.shiftStore.defaultShift.addTotalSales( + totalAmountDue, + ); + if (res) { + let writePromises = []; + + for ( + let printedReceipts = 0; + printedReceipts < + parseInt( + props.printerStore.companySettings[0] + .changeNoReceipts, + 10, + ); + printedReceipts += 1 + ) { + writePromises = []; + + writePromises.push(BluetoothSerial.write(TinyPOS.init())); + + // Header + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + props.printerStore.companySettings.length > 0 + ? props.printerStore.companySettings[0].name + ? props.printerStore.companySettings[0].name.toString() + : "" + : "" + }`, + { align: "center", size: "doubleheight" }, + true, + ), + ), + ); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + props.printerStore.companySettings.length > 0 + ? props.printerStore.companySettings[0].header.toString() + : "" + }`, + { align: "center", size: "normal" }, + true, + ), + ), + ); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + + // Date + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, + { size: "normal" }, + true, + ), + ), + ); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Cashier + + `${ + props.attendantStore.defaultAttendant + .user_name + }`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.TransactionNo + `${finalReceiptNumber}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "Mode of payment: " + + props.stateStore.payment_state[0].selected, + { align: "left", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Purchases, + { align: "center", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Items + + " " + + strings.Amount + + " ", + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + + props.receiptStore.defaultReceipt.lines.map(val => { + let finalLines = ""; + + const name = val.item_name; + + if (name.length > 14) { + let quotientValue = name.length / 14; + for ( + let quotient = 0; + quotient < parseInt(quotientValue, 10); + quotient += 1 + ) { + let currentCounter = quotient * 14; + let nameCounter = ""; + for ( + let n = currentCounter; + n < (quotient + 1) * 14; + n += 1 + ) { + nameCounter = nameCounter + name[n]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounter}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + } + if ( + name.length - parseInt(quotientValue, 10) * 14 > + 0 + ) { + let nameCounterOverflow = ""; + for ( + let m = parseInt(quotientValue, 10) * 14; + m < name.length; + m += 1 + ) { + nameCounterOverflow = nameCounterOverflow + name[m]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounterOverflow}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + } + } else { + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${name}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + } + + let priceString = formatNumber( + parseFloat(val.price, 10), + ).toString(); + let qtyString = val.qty.toString(); + let amountString = formatNumber( + parseFloat(val.price, 10) * parseFloat(val.qty, 10), + ).toString(); + + for (let ps = 0; ps < 12 - priceString.length; ps += 1) { + finalLines = finalLines + " "; + } + + finalLines = finalLines + priceString; + + for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { + finalLines = finalLines + " "; + } + finalLines = finalLines + qtyString; + + for (let as = 0; as < 14 - amountString.length; as += 1) { + finalLines = finalLines + " "; + } + + finalLines = finalLines + amountString; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${finalLines}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + if (printedReceipts === 0) { + totalPurchase = + parseFloat(totalPurchase, 10) + + parseFloat(val.price, 10) * parseFloat(val.qty, 10); + } + }); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + + let subTotal = strings.Subtotal; + let sub = formatNumber( + parseFloat( + props.receiptStore.defaultReceipt.subtotal, + 10, + ), + ).toString(); + for (let t = 0; t < 23 - sub.length; t += 1) { + subTotal = subTotal + " "; + } + subTotal = subTotal + sub; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${subTotal}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + let taxValue = strings.Tax; + let tax = formatNumber( + parseFloat( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + 10, + ), + ).toString(); + for (let t = 0; t < 29 - tax.length; t += 1) { + taxValue = taxValue + " "; + } + taxValue = taxValue + tax; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${taxValue}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + let discountValue = strings.Discount; + let discount = formatNumber( + parseFloat( + props.receiptStore.defaultReceipt.discounts, + 10, + ), + ).toString(); + for (let d = 0; d < 24 - discount.length; d += 1) { + discountValue = discountValue + " "; + } + discountValue = discountValue + discount; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${discountValue}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + + let commissionValue = strings.Commission; + + let commission_total = formatNumber( + parseFloat(commission_toto, 10), + ).toString(); + for (let d = 0; d < 22 - commission_total.length; d += 1) { + commissionValue = commissionValue + " "; + } + commissionValue = commissionValue + commission_total; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${commissionValue}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + + let total = ""; + total = total + strings.TotalAmount; + + for ( + let totalLength = 0; + totalLength < + 20 - + formatNumber(parseFloat(totalPurchase, 10)).toString() + .length; + totalLength += 1 + ) { + total = total + " "; + } + total = + total + + formatNumber( + parseFloat(totalPurchase, 10) - + parseFloat( + props.receiptStore.defaultReceipt.discounts, + 10, + ) + + parseFloat( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt + .get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + 10, + ), + ).toString(); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${total}`, + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + let cash = strings.Cash; + for ( + let cashLength = 0; + cashLength < + 28 - + formatNumber( + parseFloat( props.stateStore.payment_value, 10), + ).toString().length; + cashLength += 1 + ) { + cash = cash + " "; + } + cash = + cash + + formatNumber( + parseFloat( props.stateStore.payment_value, 10), + ).toString(); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${cash}`, + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + let change = strings.Change; + let changeValue = formatNumber( + parseFloat( + parseFloat( props.stateStore.payment_value, 10) - + (parseFloat(totalPurchase, 10) - + parseFloat( + props.receiptStore.defaultReceipt.discounts, + 10, + ) + + parseFloat( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt + .get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + 10, + )), + 10, + ), + ).toString(); + for ( + let changeLength = 0; + changeLength < 26 - changeValue.length; + changeLength += 1 + ) { + change = change + " "; + } + change = change + changeValue; + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${change}`, + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.ThisServesAsYour, + { align: "center", size: "doubleheight" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.OfficialReceipt + "\n", + { align: "center", size: "doubleheight" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + props.printerStore.companySettings.length > 0 + ? props.printerStore.companySettings[0].footer.toString() + : "" + }`, + { align: "center", size: "normal" }, + true, + ), + ), + ); + // Add 3 new lines + writePromises.push( + BluetoothSerial.write(TinyPOS.bufferedLine(3)), + ); + } + // Push drawer + writePromises.push( + BluetoothSerial.write(TinyPOS.kickCashDrawer()), + ); + writePromises.push( + BluetoothSerial.write(TinyPOS.kickCashDrawer()), + ); + Promise.all(writePromises) + .then(res2 => { + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + // add to row + + payment_add(props); + + // Reset payment amount + // setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + props.stateStore.changeValue( + "paymentAmount", + 0, + "Payment", + ); + + Toast.show({ + text: strings.TransactionCompleted, + duration: 5000, + }); + }) + .catch(err => { + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + + payment_add(props); + props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + props.stateStore.changeValue( + "paymentAmount", + 0, + "Payment", + ); + + Toast.show({ + text: err.message + strings.TransactionCompleted, + buttonText: strings.Okay, + position: "bottom", + duration: 5000, + }); + }); + } else { + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + + // add to row + payment_add(props); + + + // this.setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + props.stateStore.changeValue( + "paymentAmount", + 0, + "Payment", + ); + Toast.show({ + text: + strings.TransactionCompleted[ + strings.UnableToConnectPrinter + ], + buttonText: strings.Okay, + position: "bottom", + duration: 6000, + }); + } + + const { defaultShift } = props.shiftStore; + + // If shift started and shift hasn't ended + if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { + // Set the default receipt + const { defaultReceipt } = props.receiptStore; + + // set shift + defaultReceipt.setShift(defaultShift._id); + + const { ending_cash } = defaultShift; + + // Set the end cash + defaultShift.setEndCash( + ending_cash + defaultReceipt.netTotal, + ); + } + + // props.receiptStore.defaultReceipt.clear(); + props.receiptStore.add( + props.receiptStore.defaultReceipt, + ); + props.receiptStore.setPreviousReceipt( + props.receiptStore.defaultReceipt, + ); + let discountValueForDisplay = props.receiptStore + .defaultReceipt.discounts; + let taxesValueForDisplay = props.stateStore + .enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item; + props.receiptStore.newReceipt( + props.printerStore.companySettings[0].tax, + ); + props.receiptStore.setLastScannedBarcode(""); + props.receiptStore.unselectReceiptLine(); + props.stateStore.changeValue("selected", "Cash", "Payment"); + change_navigation(props,totalPurchase, discountValueForDisplay,taxesValueForDisplay); + }, + }, + ], + ); + }); + } +} + +export function payment_add(props){ + props.paymentStore.add({ + receipt: props.receiptStore.defaultReceipt._id.toString(), + date: Date.now(), + paid: parseInt( props.stateStore.payment_value, 10), + type: props.stateStore.payment_state[0].selected, + dateUpdated: Date.now(), + syncStatus: false, + }); +} +export function change_navigation(props,totalPurchase, discountValueForDisplay,taxesValueForDisplay){ + props.navigation.navigate("Sales", { + cash: props.stateStore.payment_value, + change: parseFloat( + parseFloat( props.stateStore.payment_value, 10) - + (parseFloat(totalPurchase, 10) - + parseFloat(discountValueForDisplay, 10) + + parseFloat(taxesValueForDisplay, 10)), + 10, + ), + }); +} diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 794cb35..488f0b4 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -41,7 +41,6 @@ import { } from "../../services/tailorder"; import { currentLanguage } from "../../translations/CurrentLanguage"; - const Sound = require("react-native-sound"); Sound.setCategory("Playback"); const beep = new Sound("beep.mp3", Sound.MAIN_BUNDLE); @@ -63,7 +62,8 @@ let strings = new LocalizedStrings(translation); @observer export default class SalesContainer extends React.Component { componentWillMount() { - const { initializeState } = this.props.stateStore; + + const { initializeState } = this.props.stateStore; // Initializing the state store initializeState(); @@ -93,6 +93,7 @@ export default class SalesContainer extends React.Component { } } + componentDidMount() { // Selected Category Index const { selectedCategoryIndex } = this.props.stateStore.sales_state[0]; @@ -105,8 +106,8 @@ export default class SalesContainer extends React.Component { } SplashScreen.hide(); - } + } onItemClick = item => { const { changeValue } = this.props.stateStore; const { setReceiptLine } = this.props.receiptStore; @@ -535,7 +536,8 @@ export default class SalesContainer extends React.Component { cash={cash} change={change} onClose={this.closeSummary} - visibility={previousReceipt ? true : false} + + visibility={previousReceipt ? false : false} lines={previousReceipt ? previousReceipt.lines.slice() : []} details={ previousReceipt && previousReceipt.lines ? previousReceipt : {} diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index 3d026e4..730fc7e 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -29,6 +29,7 @@ let strings = new LocalizedStrings(translation); "customerStore", "roleStore", "headSyncStore", + "walletStore" ) @observer export default class SettingsContainer extends React.Component { @@ -45,6 +46,7 @@ export default class SettingsContainer extends React.Component { }; } componentWillMount() { + if (this.props.printerStore.sync.length > 0) { // this.setState({ // url: this.props.printerStore.sync[0].url.toString(), @@ -202,6 +204,7 @@ export default class SettingsContainer extends React.Component { BluetoothStatus.enable(true); } } + onButtonPress = value => { this.props.printerStore.addFoundDevices(value); }; @@ -980,6 +983,8 @@ export default class SettingsContainer extends React.Component { isStackItem={stateStore.isStackItem} toggleIsStackItem={stateStore.toggleIsStackItem} restoreDefault={this.restoreDefault} + _test={this._test} + _cancel={this._cancel} /> ); } diff --git a/src/store/PosStore/DbFunctions.js b/src/store/PosStore/DbFunctions.js index 5d6a011..805634e 100644 --- a/src/store/PosStore/DbFunctions.js +++ b/src/store/PosStore/DbFunctions.js @@ -2,7 +2,6 @@ import PouchDB from "pouchdb-react-native"; import SQLite from "react-native-sqlite-2"; import SQLiteAdapterFactory from "pouchdb-adapter-react-native-sqlite"; import { getRoot } from "mobx-state-tree"; -import { unformat } from "accounting-js"; import FrappeFetch from "react-native-frappe-fetch"; import { Toast } from "native-base"; var validUrl = require("valid-url"); @@ -37,7 +36,6 @@ export function sync( jobStatus, store, ) { - // if (credentials.url !== undefined && credentials.user_name !== undefined && credentials.password !== undefined) { if (credentials.url) { if (validUrl.isWebUri(credentials.url.toLowerCase())) { return FrappeFetch.createClient({ @@ -46,11 +44,10 @@ export function sync( password: credentials.password, }) - .then(responseLog => { + .then(() => { const { Client } = FrappeFetch; return Client.postApi( "tailpos_sync.sync_pos.sync_data", - // "frappe.handler.ping", { tailposData: JSON.parse(jsonObject), trashObject: JSON.parse(trashObj), @@ -59,7 +56,7 @@ export function sync( }, ); }) - .catch(error => { + .catch(() => { store.stateStore.setIsNotSyncing(); BackgroundJob.cancel({ jobKey: "AutomaticSync" }); if (!jobStatus) { @@ -89,30 +86,6 @@ export function sync( } } -export function changeItemsStatusValue(table) { - table.allDocs({ include_docs: true }).then(entries => { - if (entries && entries.rows.length > 0) { - for (var i = 0; i < entries.rows.length; i++) { - if (entries.rows[i].doc.name) { - const entry = entries.rows[i].doc; - const objectValue = { - name: entry.name, - soldBy: entry.soldBy, - price: unformat(entry.price), - sku: entry.sku, - barcode: entry.barcode, - category: entry.category, - colorAndShape: JSON.stringify(entry.colorAndShape), - taxes: JSON.stringify(entry.taxes), - dateUpdated: entry.dateUpdated, - syncStatus: true, - }; - editFields(entry, objectValue); - } - } - } - }); -} export function saveSnapshotToDB(db, snapshot) { let updateObj = false; db.upsert(snapshot._id, function(doc) { @@ -162,8 +135,6 @@ export function getRows(obj, db, numberRows, rowsOptions) { rowsOptions.skip = 1; for (var i = 0; i < entries.rows.length; i++) { if (entries.rows[i].doc.name || entries.rows[i].doc.role) { - // entries.rows[i].doc.dateUpdated = Date.now(); - // entries.rows[i].doc.syncStatus = false; obj.add(JSON.parse(JSON.stringify(entries.rows[i].doc))); } } diff --git a/src/store/PosStore/PaymentStore.js b/src/store/PosStore/PaymentStore.js index 93802fd..853c3a6 100644 --- a/src/store/PosStore/PaymentStore.js +++ b/src/store/PosStore/PaymentStore.js @@ -21,7 +21,7 @@ export const Payment = types date: types.Date, receipt: types.string, paid: types.number, - type: types.enumeration("Type", ["Cash", "Card", "Visa", "Amex", "Sapn"]), + type: types.enumeration("Type", ["Cash", "Card", "Visa", "Amex", "Sapn", "Wallet"]), deviceId: types.optional(types.string, DeviceInfo.getDeviceId()), dateUpdated: types.optional(types.Date, Date.now), syncStatus: types.optional(types.boolean, false), diff --git a/src/store/PosStore/ReceiptStore.js b/src/store/PosStore/ReceiptStore.js index 6fc7ef8..5fb1b9b 100644 --- a/src/store/PosStore/ReceiptStore.js +++ b/src/store/PosStore/ReceiptStore.js @@ -356,8 +356,11 @@ export const Receipt = types // Yay! self.lines.splice(0, self.lines.length); }, + setAttendant(attendant) { + self.attendant = attendant; + }, completed(attendant) { - self.attendant = attendant; + self.status = "completed"; }, @@ -464,6 +467,7 @@ const Store = types setReceipt(receipt) { self.defaultReceipt = receipt; }, + async setDefaultCustomer() { return await customerDB .find({ diff --git a/src/store/PosStore/WalletStore.js b/src/store/PosStore/WalletStore.js deleted file mode 100644 index 9526bca..0000000 --- a/src/store/PosStore/WalletStore.js +++ /dev/null @@ -1,103 +0,0 @@ -import { assignUUID } from "./Utils"; -import { types } from "mobx-state-tree"; -import { openAndSyncDB, syncDB } from "./DbFunctions"; - -let db = openAndSyncDB("wallet", true); -let rowsOptions = {}; - -export const Wallet = types - .model("Wallet", { - _id: types.identifier(), - wallet_card_number: types.string, - prepaid_balance: types.optional(types.number, 0), - credit_limit: types.optional(types.number, 0), - expiry_date: types.optional(types.Date, Date.now), - syncStatus: types.optional(types.boolean, false), - }) - .preProcessSnapshot(snapshot => assignUUID(snapshot, "Wallet")) - .actions(self => ({ - postProcessSnapshot(snapshot) { - let updateObj = false; - db.upsert(snapshot._id, function(doc) { - if (!doc._id) { - doc = snapshot; - updateObj = true; - } else { - Object.keys(snapshot).forEach(function(key) { - if (!(key === "_rev")) { - if (doc[key] !== snapshot[key]) { - doc[key] = snapshot[key]; - updateObj = true; - } - } - }); - } - if (updateObj) { - return doc; - } else { - return updateObj; - } - }); - }, - edit(data) { - Object.keys(data).forEach(key => { - if (key !== "_id") { - self[key] = data[key]; - } - }); - }, - })); - -const WalletStore = types - .model("WalletStore", { - rows: types.optional(types.array(Wallet), []), - }) - .actions(self => ({ - initSync(session) { - syncDB(db, "wallet", session, () => {}); - }, - add(data) { - self.rows.push(data); - }, - destroyDb() { - db.destroy().then(function() { - db = openAndSyncDB("wallet", true); - rowsOptions = {}; - }); - }, - find(id) { - let obj = self.rows.find(data => { - return data._id === id; - }); - - if (obj) { - return obj; - } else { - db.get(id).then(doc => { - return Wallet.create(JSON.parse(JSON.stringify(doc))); - }); - } - return null; - }, - getFromDb(numberRows) { - rowsOptions.limit = numberRows; - rowsOptions.include_docs = true; - db.allDocs(rowsOptions).then(entries => { - if (entries && entries.rows.length > 0) { - rowsOptions.startKey = entries.rows[entries.rows.length - 1].id; - rowsOptions.skip = 1; - for (let i = 0; i < entries.rows.length; i++) { - if (entries.rows[i].doc._id) { - entries.rows[i].doc.dateUpdated = Date.now(); - entries.rows[i].doc.syncStatus = false; - self.add(JSON.parse(JSON.stringify(entries.rows[i].doc))); - } - } - } - }); - }, - })); - -const walletStore = WalletStore.create({}); - -export default walletStore; diff --git a/src/store/PosStore/syncInBackground.js b/src/store/PosStore/syncInBackground.js index 577f3b2..5d3f152 100644 --- a/src/store/PosStore/syncInBackground.js +++ b/src/store/PosStore/syncInBackground.js @@ -60,6 +60,8 @@ export function syncObjectValues(status, store, jobStatus) { await attendantSync(data[x], store); } else if (table === "Company") { await companySync(data[x], store); + } else if (table === "Wallet") { + await walletSync(data[x], store); } } @@ -440,31 +442,23 @@ export async function walletSync(walletObject, store) { credit_limit: walletObjectResult.syncObject.credit_limit !== null ? walletObjectResult.syncObject.credit_limit - : 0, - expiry_date: - walletObjectResult.syncObject.expiry_date !== null - ? walletObjectResult.syncObject.expiry_date - : Date.now(), + : 0 }); } else { store.walletStore.add({ - _id: walletObjectResult.syncObject.id, + _id: walletObject.syncObject.id, wallet_card_number: - walletObjectResult.syncObject.wallet_card_number !== null - ? walletObjectResult.syncObject.wallet_card_number + walletObject.syncObject.wallet_card_number !== null + ? walletObject.syncObject.wallet_card_number : "", prepaid_balance: - walletObjectResult.syncObject.prepaid_balance !== null - ? walletObjectResult.syncObject.prepaid_balance + walletObject.syncObject.prepaid_balance !== null + ? walletObject.syncObject.prepaid_balance : 0, credit_limit: - walletObjectResult.syncObject.credit_limit !== null - ? walletObjectResult.syncObject.credit_limit - : 0, - expiry_date: - walletObjectResult.syncObject.expiry_date !== null - ? walletObjectResult.syncObject.expiry_date - : Date.now(), + walletObject.syncObject.credit_limit !== null + ? walletObject.syncObject.credit_limit + : 0 }); } } diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index d2111ca..c3c6ebb 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -35,6 +35,7 @@ const StateStore = types currentConfirmation: types.optional(types.string, ""), index_value: types.optional(types.number, 0), discount_string: types.optional(types.string, "{}"), + receipt_summary: types.optional(types.string, "{}"), // Settings queueHost: types.optional(types.string, ""), hasTailOrder: types.optional(types.boolean, false), @@ -79,7 +80,10 @@ const StateStore = types }); }); }, - setDefaultValues(containerName, objectValue) { + set_receipt_summary(data) { + self.receipt_summary = data; + }, + setDefaultValues(containerName, objectValue) { let containerNameValue = ""; if (containerName === "Sales") { containerNameValue = self.sales_state; diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index fdab7ab..c41e26c 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -1,5 +1,5 @@ import * as React from "react"; -import { Dimensions, View, StyleSheet } from "react-native"; +import { Dimensions, View, StyleSheet, TouchableOpacity } from "react-native"; import { Text, Card, CardItem } from "native-base"; import { Col, Grid } from "react-native-easy-grid"; import { currentLanguage } from "../../translations/CurrentLanguage"; @@ -11,7 +11,7 @@ import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); class MoreSettingsComponent extends React.PureComponent { render() { - const { toggleItemSize } = this.props; + const { toggleItemSize, _test, _cancel } = this.props; const { smallSizeIcon, mediumSizeIcon, largeSizeIcon } = this.props.values; strings.setLanguage(currentLanguage().companyLanguage); @@ -60,7 +60,25 @@ class MoreSettingsComponent extends React.PureComponent { // disabled={!this.props.editStatus} /> + + + NFC Demo + + Test + + + + Cancel Test + + + ); diff --git a/src/stories/components/NumberKeysComponent.js b/src/stories/components/NumberKeysComponent.js index 52c1c09..3a202f3 100644 --- a/src/stories/components/NumberKeysComponent.js +++ b/src/stories/components/NumberKeysComponent.js @@ -1,6 +1,6 @@ import * as React from "react"; import { Dimensions, Text, FlatList } from "react-native"; -import { Form, Item, Button, Input } from "native-base"; +import { Form, Item, Button, Input, View } from "native-base"; import Icon from "react-native-vector-icons/FontAwesome"; var MoneyCurrency = require("money-currencies"); import { currentLanguage } from "../../translations/CurrentLanguage"; @@ -66,23 +66,39 @@ export default class NumberKeysComponent extends React.PureComponent { keyExtractor={this._extractKey} renderItem={this._renderItem} /> - + {this.props.mop === "Wallet" ? ( + + + Waiting for nfc card... + + + + ) : ( + + )} + ); } diff --git a/src/stories/screens/Payment/index.js b/src/stories/screens/Payment/index.js index 9e8a5bd..fe999f4 100644 --- a/src/stories/screens/Payment/index.js +++ b/src/stories/screens/Payment/index.js @@ -119,6 +119,7 @@ export default class Payment extends React.PureComponent { onPay={this.onPay} value={this.props.paymentValue} onChangeNumberKeyClick={this.onValueChange} + mop={this.props.values.selected} /> @@ -173,17 +174,7 @@ export default class Payment extends React.PureComponent { style={styles.printerStyle} /> - {this.props.values.selected === "Wallet" ? ( - - - - - - - ) : null} + diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index 1462262..53b0ed5 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -168,6 +168,8 @@ class Settings extends React.Component { toggleItemSize, toggleEnableOverallTax, enableOverallTax, + _test, + _cancel } = this.props; if (this.props.returnValue === strings.Bluetooth) { @@ -293,6 +295,8 @@ class Settings extends React.Component { if (this.props.returnValue === "More...") { return ( toggleItemSize(size)} From 46a0fc5f97a03c43297662e179ff83d0ebcea08e Mon Sep 17 00:00:00 2001 From: jiloysss Date: Wed, 6 Nov 2019 09:55:38 +0800 Subject: [PATCH 09/29] NFC Feature --- src/boot/background_job.js | 26 +- src/container/PaymentContainer/controller.js | 14 +- src/container/PaymentContainer/index.js | 13 +- .../nfc_manager_initialization.js | 169 +- src/container/PaymentContainer/on_pay.js | 1748 ++++++++--------- src/container/SalesContainer/index.js | 6 +- src/container/SettingsContainer/index.js | 3 +- src/store/PosStore/DbFunctions.js | 15 +- src/store/PosStore/PaymentStore.js | 9 +- src/store/PosStore/ReceiptStore.js | 8 +- src/store/PosStore/syncInBackground.js | 10 +- src/store/StateStore/StateStore.js | 8 +- .../components/MoreSettingsComponent.js | 42 +- src/stories/components/NumberKeysComponent.js | 64 +- src/stories/screens/Payment/index.js | 1 - src/stories/screens/Settings/index.js | 8 +- 16 files changed, 1056 insertions(+), 1088 deletions(-) diff --git a/src/boot/background_job.js b/src/boot/background_job.js index 4e7fdb5..b6186ed 100644 --- a/src/boot/background_job.js +++ b/src/boot/background_job.js @@ -2,17 +2,17 @@ import BackgroundJob from "react-native-background-job"; import { syncObjectValues } from "../store/PosStore/syncInBackground"; export function background_job_initialization(stores2) { - BackgroundJob.cancel({ jobKey: "AutomaticSync" }); - const backgroundJob = { - jobKey: "myJob", - job: () => syncObjectValues("sync", stores2, true), - }; - BackgroundJob.register(backgroundJob); - let backgroundSchedule = { - jobKey: "myJob", - period: 360000, - allowExecutionInForeground: true, - networkType: BackgroundJob.NETWORK_TYPE_UNMETERED, - }; - BackgroundJob.schedule(backgroundSchedule); + BackgroundJob.cancel({ jobKey: "AutomaticSync" }); + const backgroundJob = { + jobKey: "myJob", + job: () => syncObjectValues("sync", stores2, true), + }; + BackgroundJob.register(backgroundJob); + let backgroundSchedule = { + jobKey: "myJob", + period: 360000, + allowExecutionInForeground: true, + networkType: BackgroundJob.NETWORK_TYPE_UNMETERED, + }; + BackgroundJob.schedule(backgroundSchedule); } diff --git a/src/container/PaymentContainer/controller.js b/src/container/PaymentContainer/controller.js index a4c5036..46a7e8d 100644 --- a/src/container/PaymentContainer/controller.js +++ b/src/container/PaymentContainer/controller.js @@ -1,4 +1,7 @@ -import { nfc_initialization, unregister_tag_event } from "./nfc_manager_initialization"; +import { + nfc_initialization, + unregister_tag_event, +} from "./nfc_manager_initialization"; export default class PaymentController { constructor(stateStore) { this.stateStore = stateStore; @@ -9,12 +12,11 @@ export default class PaymentController { onChangePayment = (payment, props) => { this.stateStore.changeValue("selected", payment, "Payment"); if (payment === "Wallet") { - this.stateStore.setPaymentValue(this.stateStore.amount_due); - nfc_initialization(props,this.stateStore.deviceId); - + this.stateStore.setPaymentValue(this.stateStore.amount_due); + nfc_initialization(props, this.stateStore.deviceId); } else { - this.stateStore.setPaymentValue("0"); - unregister_tag_event(); + this.stateStore.setPaymentValue("0"); + unregister_tag_event(); } }; diff --git a/src/container/PaymentContainer/index.js b/src/container/PaymentContainer/index.js index 0eb5d7c..8ca5f63 100644 --- a/src/container/PaymentContainer/index.js +++ b/src/container/PaymentContainer/index.js @@ -139,12 +139,11 @@ export default class PaymentContainer extends React.Component { } }; - onPay = async () => { - const { defaultReceipt } = this.props.receiptStore; - const { defaultAttendant } = this.props.attendantStore; - defaultReceipt.setAttendant(defaultAttendant.user_name); - on_pay(this.props); + const { defaultReceipt } = this.props.receiptStore; + const { defaultAttendant } = this.props.attendantStore; + defaultReceipt.setAttendant(defaultAttendant.user_name); + on_pay(this.props); }; onBack() { @@ -306,7 +305,9 @@ export default class PaymentContainer extends React.Component { modalVisibleChange={this.controller.modalVisibleChange} navigation={this.navigation} onPrinterPress={this.onPrinterPress} - onChangePayment={(payment) => this.controller.onChangePayment(payment,this.props)} + onChangePayment={payment => + this.controller.onChangePayment(payment, this.props) + } onChangeCustomerName={this.controller.onChangeCustomerName} onChangeCustomerEmail={this.controller.onChangeCustomerEmail} onChangeCustomerPhoneNumber={this.onChangeCustomerPhoneNumber} diff --git a/src/container/PaymentContainer/nfc_manager_initialization.js b/src/container/PaymentContainer/nfc_manager_initialization.js index 02bdab8..7fca8ff 100644 --- a/src/container/PaymentContainer/nfc_manager_initialization.js +++ b/src/container/PaymentContainer/nfc_manager_initialization.js @@ -1,4 +1,4 @@ -import NfcManager from "react-native-nfc-manager"; +import NfcManager from "react-native-nfc-manager"; import { showToastDanger } from "../../utils"; import config from "../../boot/configureStore"; import { on_pay } from "./on_pay"; @@ -7,105 +7,104 @@ import FrappeFetch from "react-native-frappe-fetch"; let validUrl = require("valid-url"); const stores = config(); -export function nfc_initialization(props,deviceId) { - NfcManager.isSupported() - .then((result) => { - - if (result) { - check_tagged_nfc_card(props,deviceId); - - } else { - showToastDanger("Device does not support NFC"); - - } - - }); +export function nfc_initialization(props, deviceId) { + NfcManager.isSupported().then(result => { + if (result) { + check_tagged_nfc_card(props, deviceId); + } else { + showToastDanger("Device does not support NFC"); + } + }); } -export function check_tagged_nfc_card(props,deviceId) { - NfcManager.isEnabled() - .then(status => { - if (status){ - register_tag_event(props,deviceId); - } else { - showToastDanger("NFC is disabled"); - }}); +export function check_tagged_nfc_card(props, deviceId) { + NfcManager.isEnabled().then(status => { + if (status) { + register_tag_event(props, deviceId); + } else { + showToastDanger("NFC is disabled"); + } + }); } -export function register_tag_event(props,deviceId) { - const nfc_props = {invalidateAfterFirstRead: true, isReaderModeEnabled: true}; - const message = "Scanning NFC Card"; - NfcManager.registerTagEvent(tag => validate_tag_event(tag,props,deviceId), message, nfc_props); +export function register_tag_event(props, deviceId) { + const nfc_props = { + invalidateAfterFirstRead: true, + isReaderModeEnabled: true, + }; + const message = "Scanning NFC Card"; + NfcManager.registerTagEvent( + tag => validate_tag_event(tag, props, deviceId), + message, + nfc_props, + ); } - export function unregister_tag_event() { - NfcManager.unregisterTagEvent(); + NfcManager.unregisterTagEvent(); } export function set_attendant(props) { - const { defaultReceipt } = props.receiptStore; - const { defaultAttendant } = props.attendantStore; - defaultReceipt.setAttendant(defaultAttendant.user_name); + const { defaultReceipt } = props.receiptStore; + const { defaultAttendant } = props.attendantStore; + defaultReceipt.setAttendant(defaultAttendant.user_name); } -export async function validate_tag_event(tag, props,deviceId) { - set_attendant(props); - on_sync_tag_event(tag, props,deviceId); +export async function validate_tag_event(tag, props, deviceId) { + set_attendant(props); + on_sync_tag_event(tag, props, deviceId); } -export async function on_sync_tag_event(tag, props,deviceId) { - if (tag){ - const { url, user_name, password } = stores.printerStore.sync[0]; - const { defaultReceipt } = stores.receiptStore; - const protocol = stores.stateStore.isHttps ? "https://" : "http://"; - let site_url = protocol + url; - - const site_info = { - url: site_url.toLowerCase(), - username: user_name, - password: password, - }; - if (validUrl.isWebUri(site_url.toLowerCase())) { - FrappeFetch.createClient(site_info).then(() => { - const { Client } = FrappeFetch; - return Client.postApi( - "tailpos_sync.wallet_sync.validate_customer_wallet", - { - wallet: tag.id, - receipt: json_object(defaultReceipt), - device_id: deviceId - }, - ); - }) - - .catch(() => {}) - .then(response => response.json()) - .then(responseJson => { - validate_return_from_server(responseJson.message, props); - }); - } else { - showToastDanger("Invalid URL. Please set valid URL in Sync Settings"); - } - - } - -} - -export function validate_return_from_server(data, props){ - if (data.failed) { - showToastDanger(data.message); +export async function on_sync_tag_event(tag, props, deviceId) { + if (tag) { + const { url, user_name, password } = stores.printerStore.sync[0]; + const { defaultReceipt } = stores.receiptStore; + const protocol = stores.stateStore.isHttps ? "https://" : "http://"; + let site_url = protocol + url; + + const site_info = { + url: site_url.toLowerCase(), + username: user_name, + password: password, + }; + if (validUrl.isWebUri(site_url.toLowerCase())) { + FrappeFetch.createClient(site_info) + .then(() => { + const { Client } = FrappeFetch; + return Client.postApi( + "tailpos_sync.wallet_sync.validate_customer_wallet", + { + wallet: tag.id, + receipt: json_object(defaultReceipt), + device_id: deviceId, + }, + ); + }) + + .catch(() => {}) + .then(response => response.json()) + .then(responseJson => { + validate_return_from_server(responseJson.message, props); + }); } else { - stores.navigation = props.navigation; - on_pay(stores); + showToastDanger("Invalid URL. Please set valid URL in Sync Settings"); } + } } -export function json_object(obj){ - let receipt_json_object = {}; - Object.keys(obj).forEach(function(key) { - if (!(key === "_id")) { - receipt_json_object[key] = obj[key]; - } - }); +export function validate_return_from_server(data, props) { + if (data.failed) { + showToastDanger(data.message); + } else { + stores.navigation = props.navigation; + on_pay(stores); + } +} +export function json_object(obj) { + let receipt_json_object = {}; + Object.keys(obj).forEach(function(key) { + if (!(key === "_id")) { + receipt_json_object[key] = obj[key]; + } + }); - return receipt_json_object; + return receipt_json_object; } diff --git a/src/container/PaymentContainer/on_pay.js b/src/container/PaymentContainer/on_pay.js index 25b8a6d..1dc7229 100644 --- a/src/container/PaymentContainer/on_pay.js +++ b/src/container/PaymentContainer/on_pay.js @@ -9,904 +9,864 @@ let strings = new LocalizedStrings(translation); const moment = require("moment"); export async function setOrderCompleted(props) { - const { - queueOrigin, - currentTable, - setCurrentTable, - } = props.stateStore; - - const url = `${queueOrigin}/api/v1/complete_order`; - const fetchData = { - method: "POST", - body: JSON.stringify({ - id: currentTable, - }), - }; - - fetch(url, fetchData) - .then(res => res.json()) - .then(res => setCurrentTable(-1)); + const { queueOrigin, currentTable, setCurrentTable } = props.stateStore; + + const url = `${queueOrigin}/api/v1/complete_order`; + const fetchData = { + method: "POST", + body: JSON.stringify({ + id: currentTable, + }), + }; + + fetch(url, fetchData) + .then(res => res.json()) + .then(res => setCurrentTable(-1)); } export async function on_pay(props) { - const paymentValue = parseFloat(props.stateStore.payment_value); - const amountDue = parseFloat(props.stateStore.amount_due); - - if (paymentValue < amountDue) { - Alert.alert( - strings.Alert, - strings.AmountPaidMustBeGreaterThanOrEqualToAmountDue, - ); - } else if (paymentValue >= amountDue) { - let receiptNumber = await props.receiptStore.numberOfReceipts(); - let receiptNumberLength = receiptNumber.toString().length; - let finalReceiptNumber = ""; - for ( - let lengthNumber = 0; - lengthNumber < 15 - receiptNumberLength; - lengthNumber += 1 - ) { - finalReceiptNumber = finalReceiptNumber + "0"; - } - finalReceiptNumber = finalReceiptNumber + receiptNumber.toString(); - - const receiptCurrent = props.receiptStore.defaultReceipt; - const { deviceId } = props.stateStore; - - if (deviceId) { - receiptCurrent.setDeviceId(deviceId); - } - - BluetoothSerial.isConnected().then(res => { - let totalPurchase = 0.0; - Alert.alert( - strings.ReceiptConfirmation, // title - strings.DoYouWantToPrintReceipt, - [ - { - text: strings.No, - style: "cancel", - onPress: () => { - setOrderCompleted(props); - props.shiftStore.defaultShift.addTotalDiscount( - receiptCurrent.discounts, - ); - props.shiftStore.defaultShift.addTotalTaxes( - parseFloat(props.receiptStore.defaultReceipt.subtotal) * - (parseFloat(receiptCurrent.taxesValue) / 100), - ); - props.shiftStore.defaultShift.addNumberOfTransaction(); - - let totalAmountDue = 0.0; - - props.receiptStore.defaultReceipt.lines.map(val => { - totalAmountDue = - parseInt(totalAmountDue, 10) + - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10); - if (val.category && val.category !== "No Category") { - props.shiftStore.defaultShift.categoriesAmounts({ - name: val.category, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - if ( props.stateStore.payment_state[0].selected) { - props.shiftStore.defaultShift.mopAmounts({ - name: props.stateStore.payment_state[0].selected, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - }); - if ( - props.receiptStore.defaultReceipt.orderType !== "None" - ) { - props.shiftStore.defaultShift.addOrderType({ - amount: parseFloat(totalAmountDue, 10), - type: props.receiptStore.defaultReceipt.orderType, - }); - } - props.shiftStore.defaultShift.addTotalSales( - totalAmountDue, - ); - props.receiptStore.defaultReceipt.lines.map(val => { - totalPurchase = - parseFloat(totalPurchase, 10) + - parseFloat(val.price, 10) * parseFloat(val.qty, 10); - }); - - receiptCurrent.completed( - props.attendantStore.defaultAttendant.user_name, - ); - const { defaultShift } = props.shiftStore; - - // If shift started and shift hasn't ended - if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { - // Set the default receipt - const { defaultReceipt } = props.receiptStore; - - // set shift - defaultReceipt.setShift(defaultShift._id); - - const { ending_cash } = defaultShift; - - // Set the end cash - defaultShift.setEndCash( - ending_cash + defaultReceipt.netTotal, - ); - } - - props.receiptStore.defaultReceipt.changeTaxesAmount( - props.stateStore.enableOverallTax - ? props.receiptStore.defaultReceipt.get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - - // props.receiptStore.defaultReceipt.clear(); - payment_add(props); - - props.receiptStore.add( - props.receiptStore.defaultReceipt, - ); - props.receiptStore.setPreviousReceipt( - props.receiptStore.defaultReceipt, - ); - let discountValueForDisplay = props.receiptStore - .defaultReceipt.discounts; - let taxesValueForDisplay = props.stateStore - .enableOverallTax - ? props.receiptStore.defaultReceipt.get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item; - props.receiptStore.newReceipt( - props.printerStore.companySettings[0].tax, - ); - props.receiptStore.setLastScannedBarcode(""); - props.receiptStore.unselectReceiptLine(); - props.stateStore.changeValue("selected", "Cash", "Payment"); - change_navigation(props,totalPurchase, discountValueForDisplay,taxesValueForDisplay); - - }, - }, - { - text: strings.Yes, - onPress: () => { - setOrderCompleted(props); - props.shiftStore.defaultShift.addTotalDiscount( - receiptCurrent.discounts, - ); - props.shiftStore.defaultShift.addTotalTaxes( - parseFloat( props.receiptStore.defaultReceipt.subtotal) * - (parseFloat(receiptCurrent.taxesValue) / 100), - ); - props.shiftStore.defaultShift.addNumberOfTransaction(); - - // Let me print first - let totalAmountDue = 0.0; - let commission_toto = 0.0; - props.receiptStore.defaultReceipt.lines.map(val => { - // const { defaultShift } = props.shiftStore; - let ComHolder = JSON.parse(val.commission_details); - ComHolder.map(val2 => { - commission_toto = - commission_toto + parseInt(val2.commission_amount, 10); - }); - // defaultShift.addCommission( - // parseInt(val.commission_amount, 10), - // ); - totalAmountDue = - parseInt(totalAmountDue, 10) + - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10); - if (val.category && val.category !== "No Category") { - props.shiftStore.defaultShift.categoriesAmounts({ - name: val.category, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - if ( props.stateStore.payment_state[0].selected) { - props.shiftStore.defaultShift.mopAmounts({ - name: props.stateStore.payment_state[0].selected, - total_amount: - parseInt(val.price.toFixed(2), 10) * - parseInt(val.qty.toFixed(2), 10), - }); - } - }); - if ( - props.receiptStore.defaultReceipt.orderType !== "None" - ) { - props.shiftStore.defaultShift.addOrderType({ - amount: parseFloat(totalAmountDue, 10), - type: props.receiptStore.defaultReceipt.orderType, - }); - } - props.shiftStore.defaultShift.addTotalSales( - totalAmountDue, - ); - if (res) { - let writePromises = []; - - for ( - let printedReceipts = 0; - printedReceipts < - parseInt( - props.printerStore.companySettings[0] - .changeNoReceipts, - 10, - ); - printedReceipts += 1 - ) { - writePromises = []; - - writePromises.push(BluetoothSerial.write(TinyPOS.init())); - - // Header - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - props.printerStore.companySettings.length > 0 - ? props.printerStore.companySettings[0].name - ? props.printerStore.companySettings[0].name.toString() - : "" - : "" - }`, - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - props.printerStore.companySettings.length > 0 - ? props.printerStore.companySettings[0].header.toString() - : "" - }`, - { align: "center", size: "normal" }, - true, - ), - ), - ); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - - // Date - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, - { size: "normal" }, - true, - ), - ), - ); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Cashier + - `${ - props.attendantStore.defaultAttendant - .user_name - }`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.TransactionNo + `${finalReceiptNumber}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "Mode of payment: " + - props.stateStore.payment_state[0].selected, - { align: "left", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Purchases, - { align: "center", size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.Items + - " " + - strings.Amount + - " ", - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - - props.receiptStore.defaultReceipt.lines.map(val => { - let finalLines = ""; - - const name = val.item_name; - - if (name.length > 14) { - let quotientValue = name.length / 14; - for ( - let quotient = 0; - quotient < parseInt(quotientValue, 10); - quotient += 1 - ) { - let currentCounter = quotient * 14; - let nameCounter = ""; - for ( - let n = currentCounter; - n < (quotient + 1) * 14; - n += 1 - ) { - nameCounter = nameCounter + name[n]; - } - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${nameCounter}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - } - if ( - name.length - parseInt(quotientValue, 10) * 14 > - 0 - ) { - let nameCounterOverflow = ""; - for ( - let m = parseInt(quotientValue, 10) * 14; - m < name.length; - m += 1 - ) { - nameCounterOverflow = nameCounterOverflow + name[m]; - } - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${nameCounterOverflow}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - } - } else { - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${name}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - } - - let priceString = formatNumber( - parseFloat(val.price, 10), - ).toString(); - let qtyString = val.qty.toString(); - let amountString = formatNumber( - parseFloat(val.price, 10) * parseFloat(val.qty, 10), - ).toString(); - - for (let ps = 0; ps < 12 - priceString.length; ps += 1) { - finalLines = finalLines + " "; - } - - finalLines = finalLines + priceString; - - for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { - finalLines = finalLines + " "; - } - finalLines = finalLines + qtyString; - - for (let as = 0; as < 14 - amountString.length; as += 1) { - finalLines = finalLines + " "; - } - - finalLines = finalLines + amountString; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${finalLines}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - if (printedReceipts === 0) { - totalPurchase = - parseFloat(totalPurchase, 10) + - parseFloat(val.price, 10) * parseFloat(val.qty, 10); - } - }); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - - let subTotal = strings.Subtotal; - let sub = formatNumber( - parseFloat( - props.receiptStore.defaultReceipt.subtotal, - 10, - ), - ).toString(); - for (let t = 0; t < 23 - sub.length; t += 1) { - subTotal = subTotal + " "; - } - subTotal = subTotal + sub; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${subTotal}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - let taxValue = strings.Tax; - let tax = formatNumber( - parseFloat( - props.stateStore.enableOverallTax - ? props.receiptStore.defaultReceipt.get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - 10, - ), - ).toString(); - for (let t = 0; t < 29 - tax.length; t += 1) { - taxValue = taxValue + " "; - } - taxValue = taxValue + tax; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${taxValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - let discountValue = strings.Discount; - let discount = formatNumber( - parseFloat( - props.receiptStore.defaultReceipt.discounts, - 10, - ), - ).toString(); - for (let d = 0; d < 24 - discount.length; d += 1) { - discountValue = discountValue + " "; - } - discountValue = discountValue + discount; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${discountValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - - let commissionValue = strings.Commission; - - let commission_total = formatNumber( - parseFloat(commission_toto, 10), - ).toString(); - for (let d = 0; d < 22 - commission_total.length; d += 1) { - commissionValue = commissionValue + " "; - } - commissionValue = commissionValue + commission_total; - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${commissionValue}`, - { align: "left", size: "normal" }, - true, - ), - ), - ); - - let total = ""; - total = total + strings.TotalAmount; - - for ( - let totalLength = 0; - totalLength < - 20 - - formatNumber(parseFloat(totalPurchase, 10)).toString() - .length; - totalLength += 1 - ) { - total = total + " "; - } - total = - total + - formatNumber( - parseFloat(totalPurchase, 10) - - parseFloat( - props.receiptStore.defaultReceipt.discounts, - 10, - ) + - parseFloat( - props.stateStore.enableOverallTax - ? props.receiptStore.defaultReceipt - .get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - 10, - ), - ).toString(); - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${total}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - let cash = strings.Cash; - for ( - let cashLength = 0; - cashLength < - 28 - - formatNumber( - parseFloat( props.stateStore.payment_value, 10), - ).toString().length; - cashLength += 1 - ) { - cash = cash + " "; - } - cash = - cash + - formatNumber( - parseFloat( props.stateStore.payment_value, 10), - ).toString(); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${cash}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - let change = strings.Change; - let changeValue = formatNumber( - parseFloat( - parseFloat( props.stateStore.payment_value, 10) - - (parseFloat(totalPurchase, 10) - - parseFloat( - props.receiptStore.defaultReceipt.discounts, - 10, - ) + - parseFloat( - props.stateStore.enableOverallTax - ? props.receiptStore.defaultReceipt - .get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - 10, - )), - 10, - ), - ).toString(); - for ( - let changeLength = 0; - changeLength < 26 - changeValue.length; - changeLength += 1 - ) { - change = change + " "; - } - change = change + changeValue; - - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${change}`, - { align: "left", size: "normal", weight: "bold" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - "================================", - { size: "normal" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.ThisServesAsYour, - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - strings.OfficialReceipt + "\n", - { align: "center", size: "doubleheight" }, - true, - ), - ), - ); - writePromises.push( - BluetoothSerial.write( - TinyPOS.bufferedText( - `${ - props.printerStore.companySettings.length > 0 - ? props.printerStore.companySettings[0].footer.toString() - : "" - }`, - { align: "center", size: "normal" }, - true, - ), - ), - ); - // Add 3 new lines - writePromises.push( - BluetoothSerial.write(TinyPOS.bufferedLine(3)), - ); - } - // Push drawer - writePromises.push( - BluetoothSerial.write(TinyPOS.kickCashDrawer()), - ); - writePromises.push( - BluetoothSerial.write(TinyPOS.kickCashDrawer()), - ); - Promise.all(writePromises) - .then(res2 => { - receiptCurrent.completed( - props.attendantStore.defaultAttendant.user_name, - ); - - props.receiptStore.defaultReceipt.changeTaxesAmount( - props.stateStore.enableOverallTax - ? props.receiptStore.defaultReceipt.get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - // add to row - - payment_add(props); - - // Reset payment amount - // setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - - Toast.show({ - text: strings.TransactionCompleted, - duration: 5000, - }); - }) - .catch(err => { - receiptCurrent.completed( - props.attendantStore.defaultAttendant.user_name, - ); - - props.receiptStore.defaultReceipt.changeTaxesAmount( - props.stateStore.enableOverallTax - ? props.receiptStore.defaultReceipt.get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - - payment_add(props); - props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - - Toast.show({ - text: err.message + strings.TransactionCompleted, - buttonText: strings.Okay, - position: "bottom", - duration: 5000, - }); - }); - } else { - receiptCurrent.completed( - props.attendantStore.defaultAttendant.user_name, - ); - - props.receiptStore.defaultReceipt.changeTaxesAmount( - props.stateStore.enableOverallTax - ? props.receiptStore.defaultReceipt.get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item, - ); - - // add to row - payment_add(props); - - - // this.setState({ - // modalVisible: false, - // paymentAmount: 0, - // }); - props.stateStore.changeValue( - "modalVisible", - false, - "Payment", - ); - props.stateStore.changeValue( - "paymentAmount", - 0, - "Payment", - ); - Toast.show({ - text: - strings.TransactionCompleted[ - strings.UnableToConnectPrinter - ], - buttonText: strings.Okay, - position: "bottom", - duration: 6000, - }); - } - - const { defaultShift } = props.shiftStore; - - // If shift started and shift hasn't ended - if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { - // Set the default receipt - const { defaultReceipt } = props.receiptStore; - - // set shift - defaultReceipt.setShift(defaultShift._id); - - const { ending_cash } = defaultShift; - - // Set the end cash - defaultShift.setEndCash( - ending_cash + defaultReceipt.netTotal, - ); - } - - // props.receiptStore.defaultReceipt.clear(); - props.receiptStore.add( - props.receiptStore.defaultReceipt, - ); - props.receiptStore.setPreviousReceipt( - props.receiptStore.defaultReceipt, - ); - let discountValueForDisplay = props.receiptStore - .defaultReceipt.discounts; - let taxesValueForDisplay = props.stateStore - .enableOverallTax - ? props.receiptStore.defaultReceipt.get_tax_total - : props.receiptStore.defaultReceipt - .get_tax_total_based_on_each_item; - props.receiptStore.newReceipt( - props.printerStore.companySettings[0].tax, - ); - props.receiptStore.setLastScannedBarcode(""); - props.receiptStore.unselectReceiptLine(); - props.stateStore.changeValue("selected", "Cash", "Payment"); - change_navigation(props,totalPurchase, discountValueForDisplay,taxesValueForDisplay); - }, - }, - ], - ); - }); + const paymentValue = parseFloat(props.stateStore.payment_value); + const amountDue = parseFloat(props.stateStore.amount_due); + + if (paymentValue < amountDue) { + Alert.alert( + strings.Alert, + strings.AmountPaidMustBeGreaterThanOrEqualToAmountDue, + ); + } else if (paymentValue >= amountDue) { + let receiptNumber = await props.receiptStore.numberOfReceipts(); + let receiptNumberLength = receiptNumber.toString().length; + let finalReceiptNumber = ""; + for ( + let lengthNumber = 0; + lengthNumber < 15 - receiptNumberLength; + lengthNumber += 1 + ) { + finalReceiptNumber = finalReceiptNumber + "0"; + } + finalReceiptNumber = finalReceiptNumber + receiptNumber.toString(); + + const receiptCurrent = props.receiptStore.defaultReceipt; + const { deviceId } = props.stateStore; + + if (deviceId) { + receiptCurrent.setDeviceId(deviceId); } -} -export function payment_add(props){ - props.paymentStore.add({ - receipt: props.receiptStore.defaultReceipt._id.toString(), - date: Date.now(), - paid: parseInt( props.stateStore.payment_value, 10), - type: props.stateStore.payment_state[0].selected, - dateUpdated: Date.now(), - syncStatus: false, + BluetoothSerial.isConnected().then(res => { + let totalPurchase = 0.0; + Alert.alert( + strings.ReceiptConfirmation, // title + strings.DoYouWantToPrintReceipt, + [ + { + text: strings.No, + style: "cancel", + onPress: () => { + setOrderCompleted(props); + props.shiftStore.defaultShift.addTotalDiscount( + receiptCurrent.discounts, + ); + props.shiftStore.defaultShift.addTotalTaxes( + parseFloat(props.receiptStore.defaultReceipt.subtotal) * + (parseFloat(receiptCurrent.taxesValue) / 100), + ); + props.shiftStore.defaultShift.addNumberOfTransaction(); + + let totalAmountDue = 0.0; + + props.receiptStore.defaultReceipt.lines.map(val => { + totalAmountDue = + parseInt(totalAmountDue, 10) + + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10); + if (val.category && val.category !== "No Category") { + props.shiftStore.defaultShift.categoriesAmounts({ + name: val.category, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + if (props.stateStore.payment_state[0].selected) { + props.shiftStore.defaultShift.mopAmounts({ + name: props.stateStore.payment_state[0].selected, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + }); + if (props.receiptStore.defaultReceipt.orderType !== "None") { + props.shiftStore.defaultShift.addOrderType({ + amount: parseFloat(totalAmountDue, 10), + type: props.receiptStore.defaultReceipt.orderType, + }); + } + props.shiftStore.defaultShift.addTotalSales(totalAmountDue); + props.receiptStore.defaultReceipt.lines.map(val => { + totalPurchase = + parseFloat(totalPurchase, 10) + + parseFloat(val.price, 10) * parseFloat(val.qty, 10); + }); + + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + const { defaultShift } = props.shiftStore; + + // If shift started and shift hasn't ended + if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { + // Set the default receipt + const { defaultReceipt } = props.receiptStore; + + // set shift + defaultReceipt.setShift(defaultShift._id); + + const { ending_cash } = defaultShift; + + // Set the end cash + defaultShift.setEndCash(ending_cash + defaultReceipt.netTotal); + } + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + + // props.receiptStore.defaultReceipt.clear(); + payment_add(props); + + props.receiptStore.add(props.receiptStore.defaultReceipt); + props.receiptStore.setPreviousReceipt( + props.receiptStore.defaultReceipt, + ); + let discountValueForDisplay = + props.receiptStore.defaultReceipt.discounts; + let taxesValueForDisplay = props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item; + props.receiptStore.newReceipt( + props.printerStore.companySettings[0].tax, + ); + props.receiptStore.setLastScannedBarcode(""); + props.receiptStore.unselectReceiptLine(); + props.stateStore.changeValue("selected", "Cash", "Payment"); + change_navigation( + props, + totalPurchase, + discountValueForDisplay, + taxesValueForDisplay, + ); + }, + }, + { + text: strings.Yes, + onPress: () => { + setOrderCompleted(props); + props.shiftStore.defaultShift.addTotalDiscount( + receiptCurrent.discounts, + ); + props.shiftStore.defaultShift.addTotalTaxes( + parseFloat(props.receiptStore.defaultReceipt.subtotal) * + (parseFloat(receiptCurrent.taxesValue) / 100), + ); + props.shiftStore.defaultShift.addNumberOfTransaction(); + + // Let me print first + let totalAmountDue = 0.0; + let commission_toto = 0.0; + props.receiptStore.defaultReceipt.lines.map(val => { + // const { defaultShift } = props.shiftStore; + let ComHolder = JSON.parse(val.commission_details); + ComHolder.map(val2 => { + commission_toto = + commission_toto + parseInt(val2.commission_amount, 10); + }); + // defaultShift.addCommission( + // parseInt(val.commission_amount, 10), + // ); + totalAmountDue = + parseInt(totalAmountDue, 10) + + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10); + if (val.category && val.category !== "No Category") { + props.shiftStore.defaultShift.categoriesAmounts({ + name: val.category, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + if (props.stateStore.payment_state[0].selected) { + props.shiftStore.defaultShift.mopAmounts({ + name: props.stateStore.payment_state[0].selected, + total_amount: + parseInt(val.price.toFixed(2), 10) * + parseInt(val.qty.toFixed(2), 10), + }); + } + }); + if (props.receiptStore.defaultReceipt.orderType !== "None") { + props.shiftStore.defaultShift.addOrderType({ + amount: parseFloat(totalAmountDue, 10), + type: props.receiptStore.defaultReceipt.orderType, + }); + } + props.shiftStore.defaultShift.addTotalSales(totalAmountDue); + if (res) { + let writePromises = []; + + for ( + let printedReceipts = 0; + printedReceipts < + parseInt( + props.printerStore.companySettings[0].changeNoReceipts, + 10, + ); + printedReceipts += 1 + ) { + writePromises = []; + + writePromises.push(BluetoothSerial.write(TinyPOS.init())); + + // Header + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + props.printerStore.companySettings.length > 0 + ? props.printerStore.companySettings[0].name + ? props.printerStore.companySettings[0].name.toString() + : "" + : "" + }`, + { align: "center", size: "doubleheight" }, + true, + ), + ), + ); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + props.printerStore.companySettings.length > 0 + ? props.printerStore.companySettings[0].header.toString() + : "" + }`, + { align: "center", size: "normal" }, + true, + ), + ), + ); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + + // Date + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${moment().format("YYYY/MM/D hh:mm:ss SSS")}`, + { size: "normal" }, + true, + ), + ), + ); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Cashier + + `${props.attendantStore.defaultAttendant.user_name}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.TransactionNo + `${finalReceiptNumber}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "Mode of payment: " + + props.stateStore.payment_state[0].selected, + { align: "left", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Purchases, + { align: "center", size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.Items + + " " + + strings.Amount + + " ", + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + + props.receiptStore.defaultReceipt.lines.map(val => { + let finalLines = ""; + + const name = val.item_name; + + if (name.length > 14) { + let quotientValue = name.length / 14; + for ( + let quotient = 0; + quotient < parseInt(quotientValue, 10); + quotient += 1 + ) { + let currentCounter = quotient * 14; + let nameCounter = ""; + for ( + let n = currentCounter; + n < (quotient + 1) * 14; + n += 1 + ) { + nameCounter = nameCounter + name[n]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounter}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + } + if (name.length - parseInt(quotientValue, 10) * 14 > 0) { + let nameCounterOverflow = ""; + for ( + let m = parseInt(quotientValue, 10) * 14; + m < name.length; + m += 1 + ) { + nameCounterOverflow = nameCounterOverflow + name[m]; + } + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${nameCounterOverflow}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + } + } else { + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${name}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + } + + let priceString = formatNumber( + parseFloat(val.price, 10), + ).toString(); + let qtyString = val.qty.toString(); + let amountString = formatNumber( + parseFloat(val.price, 10) * parseFloat(val.qty, 10), + ).toString(); + + for (let ps = 0; ps < 12 - priceString.length; ps += 1) { + finalLines = finalLines + " "; + } + + finalLines = finalLines + priceString; + + for (let qt = 0; qt < 6 - qtyString.length; qt += 1) { + finalLines = finalLines + " "; + } + finalLines = finalLines + qtyString; + + for (let as = 0; as < 14 - amountString.length; as += 1) { + finalLines = finalLines + " "; + } + + finalLines = finalLines + amountString; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${finalLines}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + if (printedReceipts === 0) { + totalPurchase = + parseFloat(totalPurchase, 10) + + parseFloat(val.price, 10) * parseFloat(val.qty, 10); + } + }); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + + let subTotal = strings.Subtotal; + let sub = formatNumber( + parseFloat(props.receiptStore.defaultReceipt.subtotal, 10), + ).toString(); + for (let t = 0; t < 23 - sub.length; t += 1) { + subTotal = subTotal + " "; + } + subTotal = subTotal + sub; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${subTotal}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + let taxValue = strings.Tax; + let tax = formatNumber( + parseFloat( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + 10, + ), + ).toString(); + for (let t = 0; t < 29 - tax.length; t += 1) { + taxValue = taxValue + " "; + } + taxValue = taxValue + tax; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${taxValue}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + let discountValue = strings.Discount; + let discount = formatNumber( + parseFloat(props.receiptStore.defaultReceipt.discounts, 10), + ).toString(); + for (let d = 0; d < 24 - discount.length; d += 1) { + discountValue = discountValue + " "; + } + discountValue = discountValue + discount; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${discountValue}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + + let commissionValue = strings.Commission; + + let commission_total = formatNumber( + parseFloat(commission_toto, 10), + ).toString(); + for (let d = 0; d < 22 - commission_total.length; d += 1) { + commissionValue = commissionValue + " "; + } + commissionValue = commissionValue + commission_total; + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${commissionValue}`, + { align: "left", size: "normal" }, + true, + ), + ), + ); + + let total = ""; + total = total + strings.TotalAmount; + + for ( + let totalLength = 0; + totalLength < + 20 - + formatNumber(parseFloat(totalPurchase, 10)).toString() + .length; + totalLength += 1 + ) { + total = total + " "; + } + total = + total + + formatNumber( + parseFloat(totalPurchase, 10) - + parseFloat( + props.receiptStore.defaultReceipt.discounts, + 10, + ) + + parseFloat( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + 10, + ), + ).toString(); + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${total}`, + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + let cash = strings.Cash; + for ( + let cashLength = 0; + cashLength < + 28 - + formatNumber( + parseFloat(props.stateStore.payment_value, 10), + ).toString().length; + cashLength += 1 + ) { + cash = cash + " "; + } + cash = + cash + + formatNumber( + parseFloat(props.stateStore.payment_value, 10), + ).toString(); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${cash}`, + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + let change = strings.Change; + let changeValue = formatNumber( + parseFloat( + parseFloat(props.stateStore.payment_value, 10) - + (parseFloat(totalPurchase, 10) - + parseFloat( + props.receiptStore.defaultReceipt.discounts, + 10, + ) + + parseFloat( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + 10, + )), + 10, + ), + ).toString(); + for ( + let changeLength = 0; + changeLength < 26 - changeValue.length; + changeLength += 1 + ) { + change = change + " "; + } + change = change + changeValue; + + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${change}`, + { align: "left", size: "normal", weight: "bold" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + "================================", + { size: "normal" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.ThisServesAsYour, + { align: "center", size: "doubleheight" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + strings.OfficialReceipt + "\n", + { align: "center", size: "doubleheight" }, + true, + ), + ), + ); + writePromises.push( + BluetoothSerial.write( + TinyPOS.bufferedText( + `${ + props.printerStore.companySettings.length > 0 + ? props.printerStore.companySettings[0].footer.toString() + : "" + }`, + { align: "center", size: "normal" }, + true, + ), + ), + ); + // Add 3 new lines + writePromises.push( + BluetoothSerial.write(TinyPOS.bufferedLine(3)), + ); + } + // Push drawer + writePromises.push( + BluetoothSerial.write(TinyPOS.kickCashDrawer()), + ); + writePromises.push( + BluetoothSerial.write(TinyPOS.kickCashDrawer()), + ); + Promise.all(writePromises) + .then(res2 => { + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + // add to row + + payment_add(props); + + // Reset payment amount + // setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + props.stateStore.changeValue("paymentAmount", 0, "Payment"); + + Toast.show({ + text: strings.TransactionCompleted, + duration: 5000, + }); + }) + .catch(err => { + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + + payment_add(props); + props.stateStore.changeValue( + "modalVisible", + false, + "Payment", + ); + props.stateStore.changeValue("paymentAmount", 0, "Payment"); + + Toast.show({ + text: err.message + strings.TransactionCompleted, + buttonText: strings.Okay, + position: "bottom", + duration: 5000, + }); + }); + } else { + receiptCurrent.completed( + props.attendantStore.defaultAttendant.user_name, + ); + + props.receiptStore.defaultReceipt.changeTaxesAmount( + props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item, + ); + + // add to row + payment_add(props); + + // this.setState({ + // modalVisible: false, + // paymentAmount: 0, + // }); + props.stateStore.changeValue("modalVisible", false, "Payment"); + props.stateStore.changeValue("paymentAmount", 0, "Payment"); + Toast.show({ + text: + strings.TransactionCompleted[ + strings.UnableToConnectPrinter + ], + buttonText: strings.Okay, + position: "bottom", + duration: 6000, + }); + } + + const { defaultShift } = props.shiftStore; + + // If shift started and shift hasn't ended + if (defaultShift.shiftStarted && !defaultShift.shiftEnded) { + // Set the default receipt + const { defaultReceipt } = props.receiptStore; + + // set shift + defaultReceipt.setShift(defaultShift._id); + + const { ending_cash } = defaultShift; + + // Set the end cash + defaultShift.setEndCash(ending_cash + defaultReceipt.netTotal); + } + + // props.receiptStore.defaultReceipt.clear(); + props.receiptStore.add(props.receiptStore.defaultReceipt); + props.receiptStore.setPreviousReceipt( + props.receiptStore.defaultReceipt, + ); + let discountValueForDisplay = + props.receiptStore.defaultReceipt.discounts; + let taxesValueForDisplay = props.stateStore.enableOverallTax + ? props.receiptStore.defaultReceipt.get_tax_total + : props.receiptStore.defaultReceipt + .get_tax_total_based_on_each_item; + props.receiptStore.newReceipt( + props.printerStore.companySettings[0].tax, + ); + props.receiptStore.setLastScannedBarcode(""); + props.receiptStore.unselectReceiptLine(); + props.stateStore.changeValue("selected", "Cash", "Payment"); + change_navigation( + props, + totalPurchase, + discountValueForDisplay, + taxesValueForDisplay, + ); + }, + }, + ], + ); }); + } } -export function change_navigation(props,totalPurchase, discountValueForDisplay,taxesValueForDisplay){ - props.navigation.navigate("Sales", { - cash: props.stateStore.payment_value, - change: parseFloat( - parseFloat( props.stateStore.payment_value, 10) - - (parseFloat(totalPurchase, 10) - - parseFloat(discountValueForDisplay, 10) + - parseFloat(taxesValueForDisplay, 10)), - 10, - ), - }); + +export function payment_add(props) { + props.paymentStore.add({ + receipt: props.receiptStore.defaultReceipt._id.toString(), + date: Date.now(), + paid: parseInt(props.stateStore.payment_value, 10), + type: props.stateStore.payment_state[0].selected, + dateUpdated: Date.now(), + syncStatus: false, + }); +} +export function change_navigation( + props, + totalPurchase, + discountValueForDisplay, + taxesValueForDisplay, +) { + props.navigation.navigate("Sales", { + cash: props.stateStore.payment_value, + change: parseFloat( + parseFloat(props.stateStore.payment_value, 10) - + (parseFloat(totalPurchase, 10) - + parseFloat(discountValueForDisplay, 10) + + parseFloat(taxesValueForDisplay, 10)), + 10, + ), + }); } diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 488f0b4..7425a8c 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -62,8 +62,7 @@ let strings = new LocalizedStrings(translation); @observer export default class SalesContainer extends React.Component { componentWillMount() { - - const { initializeState } = this.props.stateStore; + const { initializeState } = this.props.stateStore; // Initializing the state store initializeState(); @@ -93,7 +92,6 @@ export default class SalesContainer extends React.Component { } } - componentDidMount() { // Selected Category Index const { selectedCategoryIndex } = this.props.stateStore.sales_state[0]; @@ -106,7 +104,6 @@ export default class SalesContainer extends React.Component { } SplashScreen.hide(); - } onItemClick = item => { const { changeValue } = this.props.stateStore; @@ -536,7 +533,6 @@ export default class SalesContainer extends React.Component { cash={cash} change={change} onClose={this.closeSummary} - visibility={previousReceipt ? false : false} lines={previousReceipt ? previousReceipt.lines.slice() : []} details={ diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index 730fc7e..42c4f20 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -29,7 +29,7 @@ let strings = new LocalizedStrings(translation); "customerStore", "roleStore", "headSyncStore", - "walletStore" + "walletStore", ) @observer export default class SettingsContainer extends React.Component { @@ -46,7 +46,6 @@ export default class SettingsContainer extends React.Component { }; } componentWillMount() { - if (this.props.printerStore.sync.length > 0) { // this.setState({ // url: this.props.printerStore.sync[0].url.toString(), diff --git a/src/store/PosStore/DbFunctions.js b/src/store/PosStore/DbFunctions.js index 805634e..ad8e318 100644 --- a/src/store/PosStore/DbFunctions.js +++ b/src/store/PosStore/DbFunctions.js @@ -46,15 +46,12 @@ export function sync( .then(() => { const { Client } = FrappeFetch; - return Client.postApi( - "tailpos_sync.sync_pos.sync_data", - { - tailposData: JSON.parse(jsonObject), - trashObject: JSON.parse(trashObj), - deviceId: credentials.deviceId, - typeOfSync: type, - }, - ); + return Client.postApi("tailpos_sync.sync_pos.sync_data", { + tailposData: JSON.parse(jsonObject), + trashObject: JSON.parse(trashObj), + deviceId: credentials.deviceId, + typeOfSync: type, + }); }) .catch(() => { store.stateStore.setIsNotSyncing(); diff --git a/src/store/PosStore/PaymentStore.js b/src/store/PosStore/PaymentStore.js index 853c3a6..f9204e3 100644 --- a/src/store/PosStore/PaymentStore.js +++ b/src/store/PosStore/PaymentStore.js @@ -21,7 +21,14 @@ export const Payment = types date: types.Date, receipt: types.string, paid: types.number, - type: types.enumeration("Type", ["Cash", "Card", "Visa", "Amex", "Sapn", "Wallet"]), + type: types.enumeration("Type", [ + "Cash", + "Card", + "Visa", + "Amex", + "Sapn", + "Wallet", + ]), deviceId: types.optional(types.string, DeviceInfo.getDeviceId()), dateUpdated: types.optional(types.Date, Date.now), syncStatus: types.optional(types.boolean, false), diff --git a/src/store/PosStore/ReceiptStore.js b/src/store/PosStore/ReceiptStore.js index 5fb1b9b..030961c 100644 --- a/src/store/PosStore/ReceiptStore.js +++ b/src/store/PosStore/ReceiptStore.js @@ -356,12 +356,10 @@ export const Receipt = types // Yay! self.lines.splice(0, self.lines.length); }, - setAttendant(attendant) { - self.attendant = attendant; - }, + setAttendant(attendant) { + self.attendant = attendant; + }, completed(attendant) { - - self.status = "completed"; }, cancelled(obj) { diff --git a/src/store/PosStore/syncInBackground.js b/src/store/PosStore/syncInBackground.js index 5d3f152..d38a60a 100644 --- a/src/store/PosStore/syncInBackground.js +++ b/src/store/PosStore/syncInBackground.js @@ -442,23 +442,23 @@ export async function walletSync(walletObject, store) { credit_limit: walletObjectResult.syncObject.credit_limit !== null ? walletObjectResult.syncObject.credit_limit - : 0 + : 0, }); } else { store.walletStore.add({ _id: walletObject.syncObject.id, wallet_card_number: - walletObject.syncObject.wallet_card_number !== null + walletObject.syncObject.wallet_card_number !== null ? walletObject.syncObject.wallet_card_number : "", prepaid_balance: - walletObject.syncObject.prepaid_balance !== null + walletObject.syncObject.prepaid_balance !== null ? walletObject.syncObject.prepaid_balance : 0, credit_limit: - walletObject.syncObject.credit_limit !== null + walletObject.syncObject.credit_limit !== null ? walletObject.syncObject.credit_limit - : 0 + : 0, }); } } diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index c3c6ebb..3343129 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -80,10 +80,10 @@ const StateStore = types }); }); }, - set_receipt_summary(data) { - self.receipt_summary = data; - }, - setDefaultValues(containerName, objectValue) { + set_receipt_summary(data) { + self.receipt_summary = data; + }, + setDefaultValues(containerName, objectValue) { let containerNameValue = ""; if (containerName === "Sales") { containerNameValue = self.sales_state; diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index c41e26c..778d0e6 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -60,25 +60,37 @@ class MoreSettingsComponent extends React.PureComponent { // disabled={!this.props.editStatus} /> - - - NFC Demo - + + + NFC Demo + - Test - + > + Test + - - Cancel Test - - + > + Cancel Test + + - ); diff --git a/src/stories/components/NumberKeysComponent.js b/src/stories/components/NumberKeysComponent.js index 3a202f3..c138204 100644 --- a/src/stories/components/NumberKeysComponent.js +++ b/src/stories/components/NumberKeysComponent.js @@ -66,39 +66,37 @@ export default class NumberKeysComponent extends React.PureComponent { keyExtractor={this._extractKey} renderItem={this._renderItem} /> - {this.props.mop === "Wallet" ? ( - - - Waiting for nfc card... - - - - ) : ( - - )} - + {this.props.mop === "Wallet" ? ( + + + Waiting for nfc card... + + + ) : ( + + )} ); } diff --git a/src/stories/screens/Payment/index.js b/src/stories/screens/Payment/index.js index fe999f4..83712e2 100644 --- a/src/stories/screens/Payment/index.js +++ b/src/stories/screens/Payment/index.js @@ -174,7 +174,6 @@ export default class Payment extends React.PureComponent { style={styles.printerStyle} /> - diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index 53b0ed5..053db4e 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -168,8 +168,8 @@ class Settings extends React.Component { toggleItemSize, toggleEnableOverallTax, enableOverallTax, - _test, - _cancel + _test, + _cancel, } = this.props; if (this.props.returnValue === strings.Bluetooth) { @@ -295,8 +295,8 @@ class Settings extends React.Component { if (this.props.returnValue === "More...") { return ( toggleItemSize(size)} From 1359a6eb8de9a3a74b7dc0a42c5bfebaa74825d1 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Wed, 6 Nov 2019 10:01:27 +0800 Subject: [PATCH 10/29] NFC Feature --- src/container/PaymentContainer/index.js | 1 - src/container/SettingsContainer/index.js | 3 -- .../components/MoreSettingsComponent.js | 34 ++----------------- src/stories/screens/Settings/index.js | 4 --- 4 files changed, 2 insertions(+), 40 deletions(-) diff --git a/src/container/PaymentContainer/index.js b/src/container/PaymentContainer/index.js index 8ca5f63..8471047 100644 --- a/src/container/PaymentContainer/index.js +++ b/src/container/PaymentContainer/index.js @@ -25,7 +25,6 @@ let strings = new LocalizedStrings(translation); "shiftStore", "attendantStore", "stateStore", - "walletStore", ) @observer export default class PaymentContainer extends React.Component { diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index 42c4f20..c66d446 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -29,7 +29,6 @@ let strings = new LocalizedStrings(translation); "customerStore", "roleStore", "headSyncStore", - "walletStore", ) @observer export default class SettingsContainer extends React.Component { @@ -982,8 +981,6 @@ export default class SettingsContainer extends React.Component { isStackItem={stateStore.isStackItem} toggleIsStackItem={stateStore.toggleIsStackItem} restoreDefault={this.restoreDefault} - _test={this._test} - _cancel={this._cancel} /> ); } diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index 778d0e6..fdab7ab 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -1,5 +1,5 @@ import * as React from "react"; -import { Dimensions, View, StyleSheet, TouchableOpacity } from "react-native"; +import { Dimensions, View, StyleSheet } from "react-native"; import { Text, Card, CardItem } from "native-base"; import { Col, Grid } from "react-native-easy-grid"; import { currentLanguage } from "../../translations/CurrentLanguage"; @@ -11,7 +11,7 @@ import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); class MoreSettingsComponent extends React.PureComponent { render() { - const { toggleItemSize, _test, _cancel } = this.props; + const { toggleItemSize } = this.props; const { smallSizeIcon, mediumSizeIcon, largeSizeIcon } = this.props.values; strings.setLanguage(currentLanguage().companyLanguage); @@ -61,36 +61,6 @@ class MoreSettingsComponent extends React.PureComponent { // disabled={!this.props.editStatus} /> - - - NFC Demo - - Test - - - - Cancel Test - - - ); diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index 053db4e..1462262 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -168,8 +168,6 @@ class Settings extends React.Component { toggleItemSize, toggleEnableOverallTax, enableOverallTax, - _test, - _cancel, } = this.props; if (this.props.returnValue === strings.Bluetooth) { @@ -295,8 +293,6 @@ class Settings extends React.Component { if (this.props.returnValue === "More...") { return ( toggleItemSize(size)} From 022eb6d1272bef00d259f12aede5f90225742bb6 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Wed, 6 Nov 2019 15:52:58 +0800 Subject: [PATCH 11/29] NFC Feature --- src/boot/index.js | 5 +++ src/boot/setup.js | 8 ++--- src/container/PaymentContainer/controller.js | 9 +++-- src/container/SettingsContainer/index.js | 19 ++++++++++ src/store/PosStore/PaymentStore.js | 24 ++++++++----- src/store/PosStore/PrinterStore.js | 6 ++++ src/store/StateStore/DefaultValues.js | 1 + src/store/StateStore/Models.js | 1 + src/store/StateStore/StateStore.js | 26 ++++++++++++++ .../components/MoreSettingsComponent.js | 19 +++++----- src/stories/screens/Payment/index.js | 35 ++++++++++++++++++- src/stories/screens/Sales/index.js | 5 +-- src/stories/screens/Settings/index.js | 2 ++ 13 files changed, 134 insertions(+), 26 deletions(-) diff --git a/src/boot/index.js b/src/boot/index.js index 129c261..594dbf2 100644 --- a/src/boot/index.js +++ b/src/boot/index.js @@ -65,6 +65,11 @@ export default function() { stores.stateStore.changeOverallTax( stores.printerStore.companySettings[0].enableOverallTax, ); + stores.stateStore.changeValue( + "multipleMop", + stores.printerStore.companySettings[0].multipleMop, + "Settings", + ); }); return app(stores); diff --git a/src/boot/setup.js b/src/boot/setup.js index 890b187..8cba5ce 100755 --- a/src/boot/setup.js +++ b/src/boot/setup.js @@ -2,15 +2,15 @@ import * as React from "react"; import { Provider } from "mobx-react/native"; import { StyleProvider } from "native-base"; import Orientation from "react-native-orientation"; -import config from "./configureStore"; -import { background_job_initialization } from "./background_job"; +// import config from "./configureStore"; +// import { background_job_initialization } from "./background_job"; import App from "../App"; import getTheme from "../theme/components"; import variables from "../theme/variables/platform"; -const stores2 = config(); -background_job_initialization(stores2); +// const stores2 = config(); +// background_job_initialization(stores2); export default function(stores) { return class Setup extends React.Component { constructor(props) { diff --git a/src/container/PaymentContainer/controller.js b/src/container/PaymentContainer/controller.js index 46a7e8d..d114aa8 100644 --- a/src/container/PaymentContainer/controller.js +++ b/src/container/PaymentContainer/controller.js @@ -1,5 +1,6 @@ import { - nfc_initialization, + // nfc_initialization, + validate_tag_event, unregister_tag_event, } from "./nfc_manager_initialization"; export default class PaymentController { @@ -13,7 +14,11 @@ export default class PaymentController { this.stateStore.changeValue("selected", payment, "Payment"); if (payment === "Wallet") { this.stateStore.setPaymentValue(this.stateStore.amount_due); - nfc_initialization(props, this.stateStore.deviceId); + // nfc_initialization(props, this.stateStore.deviceId); + validate_tag_event({ + techTypes: ["android.nfc.tech.NfcA", "android.nfc.tech.MifareClassic","android.nfc.tech.NdefFormatable" ], + id: "9AF076DF" + }, props,this.stateStore.deviceId); } else { this.stateStore.setPaymentValue("0"); unregister_tag_event(); diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index c66d446..cbd84fa 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -103,6 +103,11 @@ export default class SettingsContainer extends React.Component { this.props.printerStore.companySettings[0].largeSizeIcon, "Settings", ); + this.props.stateStore.changeValue( + "multipleMop", + this.props.printerStore.companySettings[0].multipleMop, + "Settings", + ); this.props.stateStore.changeValue( "tax", this.props.printerStore.companySettings[0].tax.toString(), @@ -861,6 +866,19 @@ export default class SettingsContainer extends React.Component { }); } }; + toggleMultipleMop = () => { + const { stateStore } = this.props; + const { multipleMop } = stateStore.settings_state[0]; + stateStore.changeValue("multipleMop", !multipleMop, "Settings"); + if (this.props.printerStore.companySettings.length > 0) { + let company = this.props.printerStore.findCompany( + this.props.printerStore.companySettings[0]._id, + ); + company.edit({ + multipleMop: !multipleMop, + }); + } + } render() { strings.setLanguage(currentLanguage().companyLanguage); const { @@ -890,6 +908,7 @@ export default class SettingsContainer extends React.Component { stateStore.changeValue("availableDevices", text, "Settings") } toggleItemSize={size => this.toggleItemSize(size)} + toggleMultipleMop={size => this.toggleMultipleMop(size)} checkBoxValueOnChange={this.onCheckBoxValueOnChange} bluetoothScannerStatus={text => { stateStore.changeValue("checkBoxBluetoothValue", text, "Settings"); diff --git a/src/store/PosStore/PaymentStore.js b/src/store/PosStore/PaymentStore.js index f9204e3..5911be5 100644 --- a/src/store/PosStore/PaymentStore.js +++ b/src/store/PosStore/PaymentStore.js @@ -14,21 +14,24 @@ import { let db = openAndSyncDB("payments", true); let rowsOptions = {}; - +export const PaymentType = types.model("PaymentType", { + type: types.enumeration("Type", [ + "Cash", + "Card", + "Visa", + "Amex", + "Sapn", + "Wallet", + ]), + amount: types.number, +}); export const Payment = types .model("Payment", { _id: types.identifier(), date: types.Date, receipt: types.string, paid: types.number, - type: types.enumeration("Type", [ - "Cash", - "Card", - "Visa", - "Amex", - "Sapn", - "Wallet", - ]), + type: types.optional(types.array(PaymentType), []), deviceId: types.optional(types.string, DeviceInfo.getDeviceId()), dateUpdated: types.optional(types.Date, Date.now), syncStatus: types.optional(types.boolean, false), @@ -41,6 +44,9 @@ export const Payment = types setDeviceId(id) { self.deviceId = id; }, + addPaymentType(paymentObj){ + self.pays.push(paymentObj); + }, edit(data) { editFields(self, data); }, diff --git a/src/store/PosStore/PrinterStore.js b/src/store/PosStore/PrinterStore.js index 50c8873..fa141dc 100644 --- a/src/store/PosStore/PrinterStore.js +++ b/src/store/PosStore/PrinterStore.js @@ -82,6 +82,7 @@ export const Company = types mediumSizeIcon: types.optional(types.boolean, false), largeSizeIcon: types.optional(types.boolean, true), hideCategory: types.optional(types.boolean, false), + multipleMop: types.optional(types.boolean, false), }) .preProcessSnapshot(snapshot => assignUUID(snapshot, "Company")) .actions(self => ({ @@ -349,6 +350,9 @@ const Store = types if (!entries.rows[i].doc.largeSizeIcon) { entries.rows[i].doc.largeSizeIcon = false; } + if (!entries.rows[i].doc.multipleMop) { + entries.rows[i].doc.largeSizeIcon = false; + } self.addCompany(JSON.parse(JSON.stringify(entries.rows[i].doc))); } @@ -366,6 +370,7 @@ const Store = types smallSizeIcon: false, mediumSizeIcon: false, largeSizeIcon: true, + multipleMop: false, }); } } else { @@ -381,6 +386,7 @@ const Store = types smallSizeIcon: false, mediumSizeIcon: false, largeSizeIcon: true, + multipleMop: false, }); } }); diff --git a/src/store/StateStore/DefaultValues.js b/src/store/StateStore/DefaultValues.js index 11cd92d..21b72be 100644 --- a/src/store/StateStore/DefaultValues.js +++ b/src/store/StateStore/DefaultValues.js @@ -69,6 +69,7 @@ export const settings = { smallSizeIcon: false, mediumSizeIcon: false, largeSizeIcon: true, + multipleMop: false, tax: "0", companyHeader: "", companyFooter: "", diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index 448a39d..2b146e8 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -75,6 +75,7 @@ export const ModelSettings = { smallSizeIcon: types.optional(types.boolean, false), mediumSizeIcon: types.optional(types.boolean, false), largeSizeIcon: types.optional(types.boolean, true), + multipleMop: types.optional(types.boolean, false), checkBoxValue: types.optional(types.string, ""), attendants: types.optional(types.string, "[]"), // attendantsInfo: {}, diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index 3343129..31ddd5f 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -36,6 +36,7 @@ const StateStore = types index_value: types.optional(types.number, 0), discount_string: types.optional(types.string, "{}"), receipt_summary: types.optional(types.string, "{}"), + payment_types: types.optional(types.string, "[]"), // Settings queueHost: types.optional(types.string, ""), hasTailOrder: types.optional(types.boolean, false), @@ -123,6 +124,31 @@ const StateStore = types containerNameValue[0][key] = value; } }); + }, + addPaymentTypes(obj) { + const cat = JSON.parse(self.payment_types); + cat.push(obj); + self.payment_types = JSON.stringify(cat); + }, + updatePaymentType(obj) { + if (obj) { + let objectLength = JSON.parse(self.payment_types); + let exists = false; + for (let i = 0; i < objectLength.length; i += 1) { + if (obj.type === objectLength[i].type) { + objectLength[i].amount = obj.amount; + exists = true; + } + } + if (!exists) { + self.addCategoryLength({ + type: obj.type, + amount: obj.amount, + }); + } else { + self.payment_types = JSON.stringify(objectLength); + } + } }, setPaymentValue(value) { self.payment_value = value; diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index fdab7ab..a94597b 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -11,8 +11,8 @@ import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); class MoreSettingsComponent extends React.PureComponent { render() { - const { toggleItemSize } = this.props; - const { smallSizeIcon, mediumSizeIcon, largeSizeIcon } = this.props.values; + const { toggleItemSize,toggleMultipleMop } = this.props; + const { smallSizeIcon, mediumSizeIcon, largeSizeIcon, multipleMop } = this.props.values; strings.setLanguage(currentLanguage().companyLanguage); return ( @@ -26,12 +26,19 @@ class MoreSettingsComponent extends React.PureComponent { + - + + toggleMultipleMop("Medium")} + /> + Item Icon Size @@ -40,7 +47,6 @@ class MoreSettingsComponent extends React.PureComponent { label="Small" checked={smallSizeIcon} onPress={() => toggleItemSize("Small")} - // disabled={!this.props.editStatus} /> @@ -48,8 +54,6 @@ class MoreSettingsComponent extends React.PureComponent { label="Medium" checked={mediumSizeIcon} onPress={() => toggleItemSize("Medium")} - - // disabled={!this.props.editStatus} /> @@ -57,10 +61,9 @@ class MoreSettingsComponent extends React.PureComponent { label="Large" checked={largeSizeIcon} onPress={() => toggleItemSize("Large")} - - // disabled={!this.props.editStatus} /> + ); diff --git a/src/stories/screens/Payment/index.js b/src/stories/screens/Payment/index.js index 83712e2..1b8f448 100644 --- a/src/stories/screens/Payment/index.js +++ b/src/stories/screens/Payment/index.js @@ -12,6 +12,8 @@ import { Item, Input, Picker, + // Textarea + } from "native-base"; import { View, Alert, StyleSheet } from "react-native"; import { formatNumber } from "accounting-js"; @@ -113,6 +115,20 @@ export default class Payment extends React.PureComponent { + + + + {PAYMENT_ITEMS} + + + + + @@ -154,9 +171,21 @@ export default class Payment extends React.PureComponent { /> - {this.renderCustomer()} + {/*{this.renderCustomer()}*/} + {/**/} + {/**/} - + {searchStatus ? this.renderSearch() : this.renderHeader()} @@ -164,7 +164,8 @@ class Sales extends React.PureComponent { /> - + + {isViewingOrder ? ( this.renderOrder() diff --git a/src/stories/screens/Settings/index.js b/src/stories/screens/Settings/index.js index 1462262..7fd0e13 100644 --- a/src/stories/screens/Settings/index.js +++ b/src/stories/screens/Settings/index.js @@ -168,6 +168,7 @@ class Settings extends React.Component { toggleItemSize, toggleEnableOverallTax, enableOverallTax, + toggleMultipleMop } = this.props; if (this.props.returnValue === strings.Bluetooth) { @@ -296,6 +297,7 @@ class Settings extends React.Component { values={values} changeNoReceipts={changeNoReceipts} toggleItemSize={size => toggleItemSize(size)} + toggleMultipleMop={size => toggleMultipleMop(size)} /> ); } From 45a38133d031cb3d09055203f444fbedd7f781c5 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Wed, 6 Nov 2019 15:53:30 +0800 Subject: [PATCH 12/29] NFC Feature --- src/boot/index.js | 10 ++--- src/container/PaymentContainer/controller.js | 18 +++++--- src/container/SettingsContainer/index.js | 24 +++++----- src/store/PosStore/PaymentStore.js | 24 +++++----- src/store/PosStore/PrinterStore.js | 4 +- src/store/StateStore/Models.js | 2 +- src/store/StateStore/StateStore.js | 44 +++++++++---------- .../components/MoreSettingsComponent.js | 20 +++++---- src/stories/screens/Payment/index.js | 35 +++++++-------- src/stories/screens/Settings/index.js | 2 +- 10 files changed, 97 insertions(+), 86 deletions(-) diff --git a/src/boot/index.js b/src/boot/index.js index 594dbf2..8353da5 100644 --- a/src/boot/index.js +++ b/src/boot/index.js @@ -65,11 +65,11 @@ export default function() { stores.stateStore.changeOverallTax( stores.printerStore.companySettings[0].enableOverallTax, ); - stores.stateStore.changeValue( - "multipleMop", - stores.printerStore.companySettings[0].multipleMop, - "Settings", - ); + stores.stateStore.changeValue( + "multipleMop", + stores.printerStore.companySettings[0].multipleMop, + "Settings", + ); }); return app(stores); diff --git a/src/container/PaymentContainer/controller.js b/src/container/PaymentContainer/controller.js index d114aa8..f4a1a81 100644 --- a/src/container/PaymentContainer/controller.js +++ b/src/container/PaymentContainer/controller.js @@ -1,6 +1,6 @@ import { // nfc_initialization, - validate_tag_event, + validate_tag_event, unregister_tag_event, } from "./nfc_manager_initialization"; export default class PaymentController { @@ -15,10 +15,18 @@ export default class PaymentController { if (payment === "Wallet") { this.stateStore.setPaymentValue(this.stateStore.amount_due); // nfc_initialization(props, this.stateStore.deviceId); - validate_tag_event({ - techTypes: ["android.nfc.tech.NfcA", "android.nfc.tech.MifareClassic","android.nfc.tech.NdefFormatable" ], - id: "9AF076DF" - }, props,this.stateStore.deviceId); + validate_tag_event( + { + techTypes: [ + "android.nfc.tech.NfcA", + "android.nfc.tech.MifareClassic", + "android.nfc.tech.NdefFormatable", + ], + id: "9AF076DF", + }, + props, + this.stateStore.deviceId, + ); } else { this.stateStore.setPaymentValue("0"); unregister_tag_event(); diff --git a/src/container/SettingsContainer/index.js b/src/container/SettingsContainer/index.js index cbd84fa..1577752 100644 --- a/src/container/SettingsContainer/index.js +++ b/src/container/SettingsContainer/index.js @@ -866,19 +866,19 @@ export default class SettingsContainer extends React.Component { }); } }; - toggleMultipleMop = () => { - const { stateStore } = this.props; - const { multipleMop } = stateStore.settings_state[0]; - stateStore.changeValue("multipleMop", !multipleMop, "Settings"); - if (this.props.printerStore.companySettings.length > 0) { - let company = this.props.printerStore.findCompany( - this.props.printerStore.companySettings[0]._id, - ); - company.edit({ - multipleMop: !multipleMop, - }); - } + toggleMultipleMop = () => { + const { stateStore } = this.props; + const { multipleMop } = stateStore.settings_state[0]; + stateStore.changeValue("multipleMop", !multipleMop, "Settings"); + if (this.props.printerStore.companySettings.length > 0) { + let company = this.props.printerStore.findCompany( + this.props.printerStore.companySettings[0]._id, + ); + company.edit({ + multipleMop: !multipleMop, + }); } + }; render() { strings.setLanguage(currentLanguage().companyLanguage); const { diff --git a/src/store/PosStore/PaymentStore.js b/src/store/PosStore/PaymentStore.js index 5911be5..762a79b 100644 --- a/src/store/PosStore/PaymentStore.js +++ b/src/store/PosStore/PaymentStore.js @@ -15,15 +15,15 @@ import { let db = openAndSyncDB("payments", true); let rowsOptions = {}; export const PaymentType = types.model("PaymentType", { - type: types.enumeration("Type", [ - "Cash", - "Card", - "Visa", - "Amex", - "Sapn", - "Wallet", - ]), - amount: types.number, + type: types.enumeration("Type", [ + "Cash", + "Card", + "Visa", + "Amex", + "Sapn", + "Wallet", + ]), + amount: types.number, }); export const Payment = types .model("Payment", { @@ -44,9 +44,9 @@ export const Payment = types setDeviceId(id) { self.deviceId = id; }, - addPaymentType(paymentObj){ - self.pays.push(paymentObj); - }, + addPaymentType(paymentObj) { + self.pays.push(paymentObj); + }, edit(data) { editFields(self, data); }, diff --git a/src/store/PosStore/PrinterStore.js b/src/store/PosStore/PrinterStore.js index fa141dc..ba2dc4a 100644 --- a/src/store/PosStore/PrinterStore.js +++ b/src/store/PosStore/PrinterStore.js @@ -370,7 +370,7 @@ const Store = types smallSizeIcon: false, mediumSizeIcon: false, largeSizeIcon: true, - multipleMop: false, + multipleMop: false, }); } } else { @@ -386,7 +386,7 @@ const Store = types smallSizeIcon: false, mediumSizeIcon: false, largeSizeIcon: true, - multipleMop: false, + multipleMop: false, }); } }); diff --git a/src/store/StateStore/Models.js b/src/store/StateStore/Models.js index 2b146e8..a5456e2 100644 --- a/src/store/StateStore/Models.js +++ b/src/store/StateStore/Models.js @@ -75,7 +75,7 @@ export const ModelSettings = { smallSizeIcon: types.optional(types.boolean, false), mediumSizeIcon: types.optional(types.boolean, false), largeSizeIcon: types.optional(types.boolean, true), - multipleMop: types.optional(types.boolean, false), + multipleMop: types.optional(types.boolean, false), checkBoxValue: types.optional(types.string, ""), attendants: types.optional(types.string, "[]"), // attendantsInfo: {}, diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index 31ddd5f..262f086 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -125,30 +125,30 @@ const StateStore = types } }); }, - addPaymentTypes(obj) { - const cat = JSON.parse(self.payment_types); - cat.push(obj); - self.payment_types = JSON.stringify(cat); - }, + addPaymentTypes(obj) { + const cat = JSON.parse(self.payment_types); + cat.push(obj); + self.payment_types = JSON.stringify(cat); + }, updatePaymentType(obj) { - if (obj) { - let objectLength = JSON.parse(self.payment_types); - let exists = false; - for (let i = 0; i < objectLength.length; i += 1) { - if (obj.type === objectLength[i].type) { - objectLength[i].amount = obj.amount; - exists = true; - } - } - if (!exists) { - self.addCategoryLength({ - type: obj.type, - amount: obj.amount, - }); - } else { - self.payment_types = JSON.stringify(objectLength); - } + if (obj) { + let objectLength = JSON.parse(self.payment_types); + let exists = false; + for (let i = 0; i < objectLength.length; i += 1) { + if (obj.type === objectLength[i].type) { + objectLength[i].amount = obj.amount; + exists = true; + } } + if (!exists) { + self.addCategoryLength({ + type: obj.type, + amount: obj.amount, + }); + } else { + self.payment_types = JSON.stringify(objectLength); + } + } }, setPaymentValue(value) { self.payment_value = value; diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index a94597b..1183a15 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -11,8 +11,13 @@ import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); class MoreSettingsComponent extends React.PureComponent { render() { - const { toggleItemSize,toggleMultipleMop } = this.props; - const { smallSizeIcon, mediumSizeIcon, largeSizeIcon, multipleMop } = this.props.values; + const { toggleItemSize, toggleMultipleMop } = this.props; + const { + smallSizeIcon, + mediumSizeIcon, + largeSizeIcon, + multipleMop, + } = this.props.values; strings.setLanguage(currentLanguage().companyLanguage); return ( @@ -32,13 +37,13 @@ class MoreSettingsComponent extends React.PureComponent { value={this.props.values.changeNoReceipts} label="Printed Receipts per Transaction" /> - + toggleMultipleMop("Medium")} + label="Multiple Mode of Payment" + checked={multipleMop} + onPress={() => toggleMultipleMop("Medium")} /> - + Item Icon Size @@ -63,7 +68,6 @@ class MoreSettingsComponent extends React.PureComponent { onPress={() => toggleItemSize("Large")} /> - ); diff --git a/src/stories/screens/Payment/index.js b/src/stories/screens/Payment/index.js index 1b8f448..b4c81f0 100644 --- a/src/stories/screens/Payment/index.js +++ b/src/stories/screens/Payment/index.js @@ -12,8 +12,7 @@ import { Item, Input, Picker, - // Textarea - + // Textarea } from "native-base"; import { View, Alert, StyleSheet } from "react-native"; import { formatNumber } from "accounting-js"; @@ -118,15 +117,15 @@ export default class Payment extends React.PureComponent { - {PAYMENT_ITEMS} + {PAYMENT_ITEMS} - @@ -176,15 +174,15 @@ export default class Payment extends React.PureComponent { {/**/} {/**/} Date: Wed, 6 Nov 2019 16:30:01 +0800 Subject: [PATCH 13/29] feat: initial sms unifonic id edit input --- src/stories/components/MoreSettingsComponent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index fdab7ab..5bd97a7 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -31,7 +31,7 @@ class MoreSettingsComponent extends React.PureComponent { value={this.props.values.changeNoReceipts} label="Printed Receipts per Transaction" /> - + Item Icon Size From ade4a70c2490c788cc41df50d7cdf490506ecd95 Mon Sep 17 00:00:00 2001 From: Bai Web and Mobile Lab Date: Wed, 6 Nov 2019 16:30:25 +0800 Subject: [PATCH 14/29] feat(ui): rename label --- src/stories/components/MoreSettingsComponent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stories/components/MoreSettingsComponent.js b/src/stories/components/MoreSettingsComponent.js index 5bd97a7..f9de595 100644 --- a/src/stories/components/MoreSettingsComponent.js +++ b/src/stories/components/MoreSettingsComponent.js @@ -31,7 +31,7 @@ class MoreSettingsComponent extends React.PureComponent { value={this.props.values.changeNoReceipts} label="Printed Receipts per Transaction" /> - + Item Icon Size From a6f977e936af6f21a6e2b093ef3110669e768c3b Mon Sep 17 00:00:00 2001 From: Bai Web and Mobile Lab Date: Wed, 6 Nov 2019 16:59:58 +0800 Subject: [PATCH 15/29] feat: voided and cancelled under ShiftStore --- src/store/PosStore/ShiftStore.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/store/PosStore/ShiftStore.js b/src/store/PosStore/ShiftStore.js index 2371986..113459a 100644 --- a/src/store/PosStore/ShiftStore.js +++ b/src/store/PosStore/ShiftStore.js @@ -49,6 +49,8 @@ export const Shift = types syncStatus: types.optional(types.boolean, false), categories_total_amounts: types.optional(types.string, "[]"), mop_total_amounts: types.optional(types.string, "[]"), + voided: types.optional(types.number, 0), + cancelled: types.optional(types.number, 0), }) .preProcessSnapshot(snapshot => assignUUID(snapshot, "Shift")) .views(self => ({ @@ -373,6 +375,8 @@ const ShiftStore = types mop_total_amounts: doc.mop_total_amounts, dateUpdated: Date.now(), syncStatus: false, + voided: doc.voided, + cancelled: doc.cancelled, }); Object.keys(doc.pays).map(key => { @@ -407,6 +411,8 @@ const ShiftStore = types mop_total_amounts: entries.rows[i].doc.mop_total_amounts, dateUpdated: Date.now(), syncStatus: false, + voided: entries.rows[i].doc.voided, + cancelled: entries.rows[i].doc.cancelled, }); Object.keys(entries.rows[i].doc.pays).map(key => { zReadingObj.addPay(entries.rows[i].doc.pays[key]); @@ -451,7 +457,8 @@ const ShiftStore = types status: report.status, categories_total_amounts: report.categories_total_amounts, mop_total_amounts: report.mop_total_amounts, - + voided: report.voided, + cancelled: report.cancelled, commissions: report.commissions, reportType: report.reportType, dateUpdated: report.dateUpdated, From 71da7e3dd085fce716ed243cec3c0a0c309c9bfc Mon Sep 17 00:00:00 2001 From: Ivan Ray Altomera Date: Fri, 8 Nov 2019 23:36:36 +0800 Subject: [PATCH 16/29] feat: initial voided and cancelled on SingleReport --- src/stories/components/SingleReportComponent.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/stories/components/SingleReportComponent.js b/src/stories/components/SingleReportComponent.js index 1365ff6..8699628 100644 --- a/src/stories/components/SingleReportComponent.js +++ b/src/stories/components/SingleReportComponent.js @@ -10,6 +10,7 @@ let MoneyCurrency = require("money-currencies"); import translation from "../.././translations/translation"; import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); + const SingleReportComponent = props => { strings.setLanguage(currentLanguage().companyLanguage); const categoryAmounts = JSON.parse(props.report.categories_total_amounts).map( @@ -303,6 +304,22 @@ const SingleReportComponent = props => { + + + Cancelled + + + 0 + + + + + Voided + + + 0 + + From d9f0d9d619d15a6158fbda6f4546b716c8440438 Mon Sep 17 00:00:00 2001 From: jiloysss Date: Thu, 14 Nov 2019 16:33:52 +0800 Subject: [PATCH 17/29] NFC Feature --- android/app/src/main/AndroidManifest.xml | 1 + src/boot/index.js | 3 + src/boot/setup.js | 8 +- src/container/PaymentContainer/controller.js | 33 +++---- src/container/PaymentContainer/index.js | 67 ++++++++++++++- .../nfc_manager_initialization.js | 27 ++++-- src/container/PaymentContainer/on_pay.js | 28 ++++-- src/container/SalesContainer/index.js | 3 - src/store/PosStore/PaymentStore.js | 17 +--- src/store/StateStore/StateStore.js | 24 +++++- src/stories/components/CategoriesComponent.js | 1 + src/stories/components/NumberKeysComponent.js | 2 +- src/stories/components/OrderItemComponent.js | 57 +++++++++--- .../components/SingleReportComponent.js | 16 ++++ src/stories/components/ViewOrderComponent.js | 11 ++- src/stories/screens/Payment/index.js | 86 +++++++++++++------ src/stories/screens/Sales/index.js | 4 +- src/stories/screens/SalesList/index.js | 70 +++++---------- src/translations/en.js | 2 + 19 files changed, 312 insertions(+), 148 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b06f030..58ce102 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -10,6 +10,7 @@ + stores.receiptStore.setDefaultCustomer()) .then(() => { + const { initializeState } = stores.stateStore; + initializeState(); + stores.receiptStore.currentReceipt( stores.printerStore.companySettings[0].tax, ); diff --git a/src/boot/setup.js b/src/boot/setup.js index 8cba5ce..890b187 100755 --- a/src/boot/setup.js +++ b/src/boot/setup.js @@ -2,15 +2,15 @@ import * as React from "react"; import { Provider } from "mobx-react/native"; import { StyleProvider } from "native-base"; import Orientation from "react-native-orientation"; -// import config from "./configureStore"; -// import { background_job_initialization } from "./background_job"; +import config from "./configureStore"; +import { background_job_initialization } from "./background_job"; import App from "../App"; import getTheme from "../theme/components"; import variables from "../theme/variables/platform"; -// const stores2 = config(); -// background_job_initialization(stores2); +const stores2 = config(); +background_job_initialization(stores2); export default function(stores) { return class Setup extends React.Component { constructor(props) { diff --git a/src/container/PaymentContainer/controller.js b/src/container/PaymentContainer/controller.js index f4a1a81..ccfc69b 100644 --- a/src/container/PaymentContainer/controller.js +++ b/src/container/PaymentContainer/controller.js @@ -1,6 +1,6 @@ import { - // nfc_initialization, - validate_tag_event, + nfc_initialization, + // validate_tag_event, unregister_tag_event, } from "./nfc_manager_initialization"; export default class PaymentController { @@ -12,21 +12,22 @@ export default class PaymentController { }; onChangePayment = (payment, props) => { this.stateStore.changeValue("selected", payment, "Payment"); - if (payment === "Wallet") { + if (payment === "Wallet" && !props.stateStore.settings_state[0].multipleMop) { this.stateStore.setPaymentValue(this.stateStore.amount_due); - // nfc_initialization(props, this.stateStore.deviceId); - validate_tag_event( - { - techTypes: [ - "android.nfc.tech.NfcA", - "android.nfc.tech.MifareClassic", - "android.nfc.tech.NdefFormatable", - ], - id: "9AF076DF", - }, - props, - this.stateStore.deviceId, - ); + nfc_initialization(props, this.stateStore.deviceId); + // validate_tag_event( + // { + // techTypes: [ + // "android.nfc.tech.NfcA", + // "android.nfc.tech.MifareClassic", + // "android.nfc.tech.NdefFormatable", + // ], + // id: "9AF076DF", + // }, + // props, + // this.stateStore.deviceId, + // ); + } else { this.stateStore.setPaymentValue("0"); unregister_tag_event(); diff --git a/src/container/PaymentContainer/index.js b/src/container/PaymentContainer/index.js index 8471047..c477026 100644 --- a/src/container/PaymentContainer/index.js +++ b/src/container/PaymentContainer/index.js @@ -5,6 +5,9 @@ import BluetoothSerial from "react-native-bluetooth-serial"; import { BluetoothStatus } from "react-native-bluetooth-status"; import * as EmailValidator from "email-validator"; import { inject, observer } from "mobx-react/native"; +import { + unregister_tag_event, +} from "./nfc_manager_initialization"; import { currentLanguage } from "../../translations/CurrentLanguage"; import PaymentController from "./controller"; @@ -35,7 +38,13 @@ export default class PaymentContainer extends React.Component { } componentWillMount() { - this.props.stateStore.setPaymentValue("0"); + const { stateStore } = this.props; + this.props.stateStore.setBalance( + (parseFloat(stateStore.amount_due,10) - parseFloat(this.get_payment_total(),10)).toString() + ); + this.props.stateStore.changeValue("selected", "Cash", "Payment"); + + this.props.stateStore.setPaymentValue("0"); if (this.props.customerStore.rows.length > 0) { this.setState({ arrayObjects: this.props.customerStore.rows.slice() }); @@ -150,7 +159,12 @@ export default class PaymentContainer extends React.Component { } navigation = () => { - this.getBluetoothState(true); + this.props.stateStore.setPaymentValue("0"); + this.props.stateStore.setMopAmount("0"); + const { stateStore } = this.props; + stateStore.resetPaymentTypes(); + unregister_tag_event(); + this.getBluetoothState(true); this.onBack(); }; onPrinterPress = () => { @@ -283,12 +297,58 @@ export default class PaymentContainer extends React.Component { this.props.stateStore.changeValue("customerPhoneNumber", "", "Payment"); this.props.stateStore.changeValue("customerNotes", "", "Payment"); }; + get_payment_total = () => { + let payment_data = JSON.parse(this.props.stateStore.payment_types); + let total = 0; + for (let i = 0; i < payment_data.length; i += 1){ + total += payment_data[i].amount; + } + return total; + + } + addMultipleMop = () => { + const { stateStore } = this.props; + if (parseInt(this.props.stateStore.payment_value, 10) > 0){ + stateStore.updatePaymentType({ + type: this.props.stateStore.payment_state[0].selected, + amount: parseInt(this.props.stateStore.payment_value, 10) + }); + stateStore.setMopAmount( + this.get_payment_total().toString() + ); + stateStore.setBalance( + (parseFloat(stateStore.amount_due,10) - parseFloat(this.get_payment_total(),10)).toString() + ); + stateStore.setPaymentValue("0"); + } else { + Toast.show({ + text: "Please input amount greater than 0", + buttonText: strings.Okay, + position: "bottom", + duration: 6000, + }); + } + + } + removeMop = () => { + const { stateStore } = this.props; + stateStore.removePaymentType(); + stateStore.setMopAmount( + this.get_payment_total().toString() + ); + stateStore.setBalance( + (parseFloat(stateStore.amount_due,10) - parseFloat(this.get_payment_total(),10)).toString() + ); + } render() { strings.setLanguage(currentLanguage().companyLanguage); return ( ); } diff --git a/src/container/PaymentContainer/nfc_manager_initialization.js b/src/container/PaymentContainer/nfc_manager_initialization.js index 7fca8ff..bbfc716 100644 --- a/src/container/PaymentContainer/nfc_manager_initialization.js +++ b/src/container/PaymentContainer/nfc_manager_initialization.js @@ -1,7 +1,8 @@ import NfcManager from "react-native-nfc-manager"; -import { showToastDanger } from "../../utils"; +import { showToastDanger, showToast } from "../../utils"; import config from "../../boot/configureStore"; import { on_pay } from "./on_pay"; +import { NetInfo } from "react-native"; import FrappeFetch from "react-native-frappe-fetch"; let validUrl = require("valid-url"); @@ -33,6 +34,7 @@ export function register_tag_event(props, deviceId) { isReaderModeEnabled: true, }; const message = "Scanning NFC Card"; + showToast("Please Scan Card Now"); NfcManager.registerTagEvent( tag => validate_tag_event(tag, props, deviceId), message, @@ -50,14 +52,26 @@ export function set_attendant(props) { } export async function validate_tag_event(tag, props, deviceId) { set_attendant(props); - on_sync_tag_event(tag, props, deviceId); + check_internet_connection(tag, props, deviceId); +} + +export async function check_internet_connection(tag, props, deviceId) { + NetInfo.isConnected.fetch().then(async isConnected => { + if (isConnected) { + on_sync_tag_event(tag, props, deviceId); + } else { + showToastDanger("No Internet Connection. Please Check"); + } + }); + } export async function on_sync_tag_event(tag, props, deviceId) { if (tag) { - const { url, user_name, password } = stores.printerStore.sync[0]; + + const { url, user_name, password, isHttps } = stores.printerStore.sync[0]; const { defaultReceipt } = stores.receiptStore; - const protocol = stores.stateStore.isHttps ? "https://" : "http://"; + const protocol = isHttps ? "https://" : "http://"; let site_url = protocol + url; const site_info = { @@ -78,12 +92,12 @@ export async function on_sync_tag_event(tag, props, deviceId) { }, ); }) - .catch(() => {}) .then(response => response.json()) .then(responseJson => { validate_return_from_server(responseJson.message, props); - }); + }) + .catch(() => showToastDanger("Please check your credentials in Sync settings")); } else { showToastDanger("Invalid URL. Please set valid URL in Sync Settings"); } @@ -94,6 +108,7 @@ export function validate_return_from_server(data, props) { if (data.failed) { showToastDanger(data.message); } else { + showToast("Wallet Scanned Successfully"); stores.navigation = props.navigation; on_pay(stores); } diff --git a/src/container/PaymentContainer/on_pay.js b/src/container/PaymentContainer/on_pay.js index 1dc7229..bcdea5b 100644 --- a/src/container/PaymentContainer/on_pay.js +++ b/src/container/PaymentContainer/on_pay.js @@ -24,7 +24,7 @@ export async function setOrderCompleted(props) { .then(res => setCurrentTable(-1)); } export async function on_pay(props) { - const paymentValue = parseFloat(props.stateStore.payment_value); + const paymentValue = props.stateStore.settings_state[0].multipleMop ? parseFloat(props.stateStore.payment_amount) : parseFloat(props.stateStore.payment_value); const amountDue = parseFloat(props.stateStore.amount_due); if (paymentValue < amountDue) { @@ -595,7 +595,7 @@ export async function on_pay(props) { cashLength < 28 - formatNumber( - parseFloat(props.stateStore.payment_value, 10), + props.stateStore.settings_state[0].multipleMop ? parseFloat(props.stateStore.payment_amount) : parseFloat(props.stateStore.payment_value, 10), ).toString().length; cashLength += 1 ) { @@ -604,7 +604,7 @@ export async function on_pay(props) { cash = cash + formatNumber( - parseFloat(props.stateStore.payment_value, 10), + props.stateStore.settings_state[0].multipleMop ? parseFloat(props.stateStore.payment_amount) : parseFloat(props.stateStore.payment_value, 10), ).toString(); writePromises.push( BluetoothSerial.write( @@ -618,7 +618,7 @@ export async function on_pay(props) { let change = strings.Change; let changeValue = formatNumber( parseFloat( - parseFloat(props.stateStore.payment_value, 10) - + (props.stateStore.settings_state[0].multipleMop ? parseFloat(props.stateStore.payment_amount) : parseFloat(props.stateStore.payment_value, 10)) - (parseFloat(totalPurchase, 10) - parseFloat( props.receiptStore.defaultReceipt.discounts, @@ -840,19 +840,31 @@ export async function on_pay(props) { ], ); }); + props.stateStore.resetPaymentTypes(); } } export function payment_add(props) { + props.paymentStore.add({ receipt: props.receiptStore.defaultReceipt._id.toString(), date: Date.now(), - paid: parseInt(props.stateStore.payment_value, 10), - type: props.stateStore.payment_state[0].selected, + paid: props.stateStore.settings_state[0].multipleMop ? parseFloat(props.stateStore.payment_amount) : parseInt(props.stateStore.payment_value, 10), + type: props.stateStore.settings_state[0].multipleMop ? props.stateStore.payment_types : not_multiple_payment(props), dateUpdated: Date.now(), syncStatus: false, }); } + +export function not_multiple_payment(props) { + let single_payment = []; + + single_payment.push({ + type: props.stateStore.payment_state[0].selected, + amount: parseInt(props.stateStore.amount_due, 10) + }); + return JSON.stringify(single_payment); +} export function change_navigation( props, totalPurchase, @@ -860,9 +872,9 @@ export function change_navigation( taxesValueForDisplay, ) { props.navigation.navigate("Sales", { - cash: props.stateStore.payment_value, + cash: props.stateStore.settings_state[0].multipleMop ? parseFloat(props.stateStore.payment_amount) : props.stateStore.payment_value, change: parseFloat( - parseFloat(props.stateStore.payment_value, 10) - + (props.stateStore.settings_state[0].multipleMop ? parseFloat(props.stateStore.payment_amount) : parseFloat(props.stateStore.payment_value, 10)) - (parseFloat(totalPurchase, 10) - parseFloat(discountValueForDisplay, 10) + parseFloat(taxesValueForDisplay, 10)), diff --git a/src/container/SalesContainer/index.js b/src/container/SalesContainer/index.js index 7425a8c..9e57972 100644 --- a/src/container/SalesContainer/index.js +++ b/src/container/SalesContainer/index.js @@ -62,10 +62,7 @@ let strings = new LocalizedStrings(translation); @observer export default class SalesContainer extends React.Component { componentWillMount() { - const { initializeState } = this.props.stateStore; - // Initializing the state store - initializeState(); this.getBluetoothState(); const { params } = this.props.navigation.state; diff --git a/src/store/PosStore/PaymentStore.js b/src/store/PosStore/PaymentStore.js index 762a79b..e6ccab3 100644 --- a/src/store/PosStore/PaymentStore.js +++ b/src/store/PosStore/PaymentStore.js @@ -14,24 +14,14 @@ import { let db = openAndSyncDB("payments", true); let rowsOptions = {}; -export const PaymentType = types.model("PaymentType", { - type: types.enumeration("Type", [ - "Cash", - "Card", - "Visa", - "Amex", - "Sapn", - "Wallet", - ]), - amount: types.number, -}); + export const Payment = types .model("Payment", { _id: types.identifier(), date: types.Date, receipt: types.string, paid: types.number, - type: types.optional(types.array(PaymentType), []), + type: types.optional(types.string, ""), deviceId: types.optional(types.string, DeviceInfo.getDeviceId()), dateUpdated: types.optional(types.Date, Date.now), syncStatus: types.optional(types.boolean, false), @@ -44,9 +34,6 @@ export const Payment = types setDeviceId(id) { self.deviceId = id; }, - addPaymentType(paymentObj) { - self.pays.push(paymentObj); - }, edit(data) { editFields(self, data); }, diff --git a/src/store/StateStore/StateStore.js b/src/store/StateStore/StateStore.js index 17fdf1b..d13d60a 100644 --- a/src/store/StateStore/StateStore.js +++ b/src/store/StateStore/StateStore.js @@ -37,6 +37,8 @@ const StateStore = types discount_string: types.optional(types.string, "{}"), receipt_summary: types.optional(types.string, "{}"), payment_types: types.optional(types.string, "[]"), + payment_amount: types.optional(types.string, "0"), + balance: types.optional(types.string, "0"), // Settings queueHost: types.optional(types.string, ""), hasTailOrder: types.optional(types.boolean, false), @@ -125,10 +127,13 @@ const StateStore = types } }); }, + resetPaymentTypes(){ + self.payment_types = "[]"; + }, addPaymentTypes(obj) { - const cat = JSON.parse(self.payment_types); - cat.push(obj); - self.payment_types = JSON.stringify(cat); + let payment_types = JSON.parse(self.payment_types); + payment_types.push(obj); + self.payment_types = JSON.stringify(payment_types); }, updatePaymentType(obj) { if (obj) { @@ -141,7 +146,7 @@ const StateStore = types } } if (!exists) { - self.addCategoryLength({ + self.addPaymentTypes({ type: obj.type, amount: obj.amount, }); @@ -150,8 +155,19 @@ const StateStore = types } } }, + removePaymentType(){ + let objectLength = JSON.parse(self.payment_types); + let filtered_items = objectLength.filter(payment_type => payment_type.type !== self.payment_state[0].selected); + self.payment_types = JSON.stringify(filtered_items); + }, setPaymentValue(value) { self.payment_value = value; + }, + setMopAmount(value) { + self.payment_amount = value; + }, + setBalance(value) { + self.balance = value; }, setAmountDue(value) { self.amount_due = value; diff --git a/src/stories/components/CategoriesComponent.js b/src/stories/components/CategoriesComponent.js index dfdfc45..671d655 100644 --- a/src/stories/components/CategoriesComponent.js +++ b/src/stories/components/CategoriesComponent.js @@ -1,6 +1,7 @@ import * as React from "react"; import { FlatList, View, Dimensions } from "react-native"; import { Text, Button } from "native-base"; + import { currentLanguage } from "../../translations/CurrentLanguage"; import translation from "../.././translations/translation"; diff --git a/src/stories/components/NumberKeysComponent.js b/src/stories/components/NumberKeysComponent.js index c138204..f71b7b5 100644 --- a/src/stories/components/NumberKeysComponent.js +++ b/src/stories/components/NumberKeysComponent.js @@ -66,7 +66,7 @@ export default class NumberKeysComponent extends React.PureComponent { keyExtractor={this._extractKey} renderItem={this._renderItem} /> - {this.props.mop === "Wallet" ? ( + {this.props.mop === "Wallet" && !this.props.multipleMop ? ( - - + + [{strings.ORDER}-{id}] - - {strings.TableNo} {tableNo} + + {type} {strings.TableNo} {tableNo} ); } } - const styles = StyleSheet.create({ view: { margin: 15, - width: 180, - height: 180, borderRadius: 180 / 2, justifyContent: "center", backgroundColor: "#afafaf", }, + largeSizeIcon: { + width: 160, + height: 160, + }, + mediumSizeIcon: { + width: 110, + height: 110, + }, + smallSizeIcon: { + width: 80, + height: 80, + }, takeAwayView: { backgroundColor: "#ffb020", }, - text: { + //SMALL + smalltext: { + fontSize: 13, + fontWeight: "bold", + textAlign: "center", + }, + smallOrderText: { + fontSize: 12, + fontWeight: "bold", + textAlign: "center", + }, + //MEDIUM + mediumtext: { + fontSize: 17, + fontWeight: "bold", + textAlign: "center", + }, + mediumOrderText: { + fontSize: 15, + fontWeight: "bold", + textAlign: "center", + }, + //LARGE + largetext: { fontSize: 21, fontWeight: "bold", textAlign: "center", }, - orderText: { + largeOrderText: { fontSize: 18, fontWeight: "bold", textAlign: "center", }, + }); export default OrderItemComponent; diff --git a/src/stories/components/SingleReportComponent.js b/src/stories/components/SingleReportComponent.js index 1365ff6..a641e5e 100644 --- a/src/stories/components/SingleReportComponent.js +++ b/src/stories/components/SingleReportComponent.js @@ -303,6 +303,22 @@ const SingleReportComponent = props => { + + + Voided + + + {props.report.voided} + + + + + Cancelled + + + {props.report.cancelled} + + diff --git a/src/stories/components/ViewOrderComponent.js b/src/stories/components/ViewOrderComponent.js index f6c40ee..21a61cb 100644 --- a/src/stories/components/ViewOrderComponent.js +++ b/src/stories/components/ViewOrderComponent.js @@ -20,14 +20,17 @@ import LocalizedStrings from "react-native-localization"; let strings = new LocalizedStrings(translation); class ViewOrderComponent extends React.PureComponent { renderOrderItem = ({ item, index }) => { - const { onTableClick, onTableLongPress } = this.props; - if (!item.is_finished) { + const { onTableClick, onTableLongPress,company } = this.props; + + if (!item.is_fulfilled) { return ( @@ -35,7 +38,7 @@ class ViewOrderComponent extends React.PureComponent { } }; renderOrders() { - const { orders } = this.props; + const { orders, company } = this.props; if (orders.length === 0) { return ( @@ -51,7 +54,7 @@ class ViewOrderComponent extends React.PureComponent { return ( ); diff --git a/src/stories/screens/Payment/index.js b/src/stories/screens/Payment/index.js index b4c81f0..7fafaa5 100644 --- a/src/stories/screens/Payment/index.js +++ b/src/stories/screens/Payment/index.js @@ -12,7 +12,8 @@ import { Item, Input, Picker, - // Textarea + Textarea, + Text } from "native-base"; import { View, Alert, StyleSheet } from "react-native"; import { formatNumber } from "accounting-js"; @@ -42,7 +43,14 @@ export default class Payment extends React.PureComponent { onValueChange = text => { this.props.onValueChange(text); }; - + payment_type = () => { + const { paymentTypes } = this.props; + let payment_types_values = ""; + for (let i = 0; i < paymentTypes.length; i += 1){ + payment_types_values += paymentTypes[i].type + " - " + paymentTypes[i].amount.toString() + "\n"; + } + return payment_types_values; + }; onPay = () => { Alert.alert( strings.ConfirmPayment, @@ -90,7 +98,8 @@ export default class Payment extends React.PureComponent { let mc = new MoneyCurrency( this.props.currency ? this.props.currency : "PHP", ); - const amountValue = parseFloat(this.props.paymentValue); + const amountValue = this.props.settings_state.multipleMop ? parseFloat(this.props.payment_amount_multiple) : parseFloat(this.props.paymentValue); + const amountDue = parseFloat(this.props.amountDue); let change = 0; @@ -113,9 +122,12 @@ export default class Payment extends React.PureComponent {
- + {this.props.settings_state.multipleMop ? ( - + + - - + + ) : null } @@ -171,28 +187,43 @@ export default class Payment extends React.PureComponent { {/*{this.renderCustomer()}*/} - - {/**/} - {/**/} - - + +