Skip to content

Commit c54b898

Browse files
authored
Merge branch 'development' into development
2 parents 0c61d0b + d5ba9cf commit c54b898

File tree

15 files changed

+278
-78
lines changed

15 files changed

+278
-78
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ repositories {
9898
dependencies {
9999
def lifecycle_version = "2.2.0-alpha01"
100100
def koin_version = "2.0.0-GA6"
101-
def roomVersion = "2.1.0-beta01"
101+
def roomVersion = "2.1.0-rc01"
102102
def ktx_version = "1.0.0"
103103
def ktx2_version = "2.0.0"
104104
def nav_version = "2.1.0-alpha04"

app/schemas/org.fossasia.openevent.general.OpenEventDatabase/6.json

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"formatVersion": 1,
33
"database": {
44
"version": 6,
5-
"identityHash": "24ed50935955154c79491815778897fb",
5+
"identityHash": "c29e46595502e4aa3dfd4c5c66474e4a",
66
"entities": [
77
{
88
"tableName": "Event",
@@ -681,7 +681,7 @@
681681
},
682682
{
683683
"tableName": "Attendee",
684-
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `firstname` TEXT, `lastname` TEXT, `email` TEXT, `address` TEXT, `city` TEXT, `state` TEXT, `country` TEXT, `isCheckedIn` INTEGER, `pdfUrl` TEXT, `ticketId` TEXT, `event` INTEGER, `ticket` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`event`) REFERENCES `Event`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`ticket`) REFERENCES `Ticket`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
684+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `firstname` TEXT, `lastname` TEXT, `email` TEXT, `address` TEXT, `city` TEXT, `state` TEXT, `country` TEXT, `isCheckedIn` INTEGER, `checkinTimes` TEXT, `isCheckedOut` INTEGER NOT NULL, `pdfUrl` TEXT, `ticketId` TEXT, `event` INTEGER, `ticket` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`event`) REFERENCES `Event`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`ticket`) REFERENCES `Ticket`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
685685
"fields": [
686686
{
687687
"fieldPath": "id",
@@ -737,6 +737,18 @@
737737
"affinity": "INTEGER",
738738
"notNull": false
739739
},
740+
{
741+
"fieldPath": "checkinTimes",
742+
"columnName": "checkinTimes",
743+
"affinity": "TEXT",
744+
"notNull": false
745+
},
746+
{
747+
"fieldPath": "isCheckedOut",
748+
"columnName": "isCheckedOut",
749+
"affinity": "INTEGER",
750+
"notNull": true
751+
},
740752
{
741753
"fieldPath": "pdfUrl",
742754
"columnName": "pdfUrl",
@@ -872,7 +884,7 @@
872884
},
873885
{
874886
"tableName": "Order",
875-
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `paymentMode` TEXT, `country` TEXT, `status` TEXT, `amount` REAL NOT NULL, `identifier` TEXT, `orderNotes` TEXT, `completedAt` TEXT, `city` TEXT, `address` TEXT, `createdAt` TEXT, `zipcode` TEXT, `paidVia` TEXT, `discountCodeId` TEXT, `ticketsPdfUrl` TEXT, `transactionId` TEXT, `event` INTEGER, `attendees` TEXT NOT NULL, PRIMARY KEY(`id`))",
887+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `paymentMode` TEXT, `country` TEXT, `status` TEXT, `amount` REAL NOT NULL, `identifier` TEXT, `orderNotes` TEXT, `completedAt` TEXT, `city` TEXT, `address` TEXT, `createdAt` TEXT, `zipcode` TEXT, `paidVia` TEXT, `discountCodeId` TEXT, `ticketsPdfUrl` TEXT, `transactionId` TEXT, `isBillingEnabled` INTEGER NOT NULL, `taxBusinessInfo` TEXT, `company` TEXT, `event` INTEGER, `attendees` TEXT NOT NULL, PRIMARY KEY(`id`))",
876888
"fields": [
877889
{
878890
"fieldPath": "id",
@@ -970,6 +982,24 @@
970982
"affinity": "TEXT",
971983
"notNull": false
972984
},
985+
{
986+
"fieldPath": "isBillingEnabled",
987+
"columnName": "isBillingEnabled",
988+
"affinity": "INTEGER",
989+
"notNull": true
990+
},
991+
{
992+
"fieldPath": "taxBusinessInfo",
993+
"columnName": "taxBusinessInfo",
994+
"affinity": "TEXT",
995+
"notNull": false
996+
},
997+
{
998+
"fieldPath": "company",
999+
"columnName": "company",
1000+
"affinity": "TEXT",
1001+
"notNull": false
1002+
},
9731003
{
9741004
"fieldPath": "event",
9751005
"columnName": "event",
@@ -1636,7 +1666,7 @@
16361666
"views": [],
16371667
"setupQueries": [
16381668
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
1639-
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"24ed50935955154c79491815778897fb\")"
1669+
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"c29e46595502e4aa3dfd4c5c66474e4a\")"
16401670
]
16411671
}
16421672
}

app/src/main/java/org/fossasia/openevent/general/attendees/Attendee.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ data class Attendee(
3434
val state: String? = null,
3535
val country: String? = null,
3636
val isCheckedIn: Boolean? = false,
37+
val checkinTimes: String? = null,
38+
val isCheckedOut: Boolean = false,
3739
val pdfUrl: String? = null,
3840
val ticketId: String? = null,
3941
@ColumnInfo(index = true)

app/src/main/java/org/fossasia/openevent/general/attendees/AttendeeFragment.kt

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ import kotlinx.android.synthetic.main.fragment_attendee.view.city
7171
import kotlinx.android.synthetic.main.fragment_attendee.view.company
7272
import kotlinx.android.synthetic.main.fragment_attendee.view.taxId
7373
import kotlinx.android.synthetic.main.fragment_attendee.view.address
74+
import kotlinx.android.synthetic.main.fragment_attendee.view.firstNameLayout
75+
import kotlinx.android.synthetic.main.fragment_attendee.view.lastNameLayout
76+
import kotlinx.android.synthetic.main.fragment_attendee.view.emailLayout
77+
import kotlinx.android.synthetic.main.fragment_attendee.view.companyLayout
78+
import kotlinx.android.synthetic.main.fragment_attendee.view.addressLayout
79+
import kotlinx.android.synthetic.main.fragment_attendee.view.cvcLayout
80+
import kotlinx.android.synthetic.main.fragment_attendee.view.cityLayout
81+
import kotlinx.android.synthetic.main.fragment_attendee.view.postalCodeLayout
82+
import kotlinx.android.synthetic.main.fragment_attendee.view.cardNumberLayout
7483
import org.fossasia.openevent.general.BuildConfig
7584
import org.fossasia.openevent.general.R
7685
import org.fossasia.openevent.general.attendees.forms.CustomForm
@@ -87,6 +96,9 @@ import org.fossasia.openevent.general.utils.extensions.nonNull
8796
import org.fossasia.openevent.general.utils.nullToEmpty
8897
import org.koin.androidx.viewmodel.ext.android.viewModel
8998
import org.fossasia.openevent.general.utils.Utils.setToolbar
99+
import org.fossasia.openevent.general.utils.setRequired
100+
import org.fossasia.openevent.general.utils.checkEmpty
101+
import org.fossasia.openevent.general.utils.checkValidEmail
90102
import org.jetbrains.anko.design.longSnackbar
91103
import org.jetbrains.anko.design.snackbar
92104
import java.util.Calendar
@@ -247,6 +259,9 @@ class AttendeeFragment : Fragment() {
247259
}
248260

249261
private fun setupUser() {
262+
rootView.firstNameLayout.setRequired()
263+
rootView.lastNameLayout.setRequired()
264+
rootView.emailLayout.setRequired()
250265
attendeeViewModel.user
251266
.nonNull()
252267
.observe(viewLifecycleOwner, Observer { user ->
@@ -352,6 +367,10 @@ class AttendeeFragment : Fragment() {
352367
}
353368

354369
private fun setupBillingInfo() {
370+
rootView.companyLayout.setRequired()
371+
rootView.addressLayout.setRequired()
372+
rootView.cityLayout.setRequired()
373+
rootView.postalCodeLayout.setRequired()
355374
rootView.billingInfoContainer.isVisible = rootView.billingEnabledCheckbox.isChecked
356375
attendeeViewModel.billingEnabled = rootView.billingEnabledCheckbox.isChecked
357376
rootView.billingEnabledCheckbox.setOnCheckedChangeListener { _, isChecked ->
@@ -433,6 +452,8 @@ class AttendeeFragment : Fragment() {
433452
}
434453

435454
private fun setupCardNumber() {
455+
rootView.cardNumberLayout.setRequired()
456+
rootView.cvcLayout.setRequired()
436457
rootView.cardNumber.addTextChangedListener(object : TextWatcher {
437458
override fun afterTextChanged(s: Editable?) { /*Do Nothing*/ }
438459
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { /*Do Nothing*/ }
@@ -510,7 +531,6 @@ class AttendeeFragment : Fragment() {
510531
private fun setupYearOptions() {
511532
val year = ArrayList<String>()
512533
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
513-
year.add(getString(R.string.year_string))
514534
val a = currentYear + 20
515535
for (i in currentYear..a) {
516536
year.add(i.toString())
@@ -535,7 +555,6 @@ class AttendeeFragment : Fragment() {
535555

536556
private fun setupCardType() {
537557
val cardType = ArrayList<String>()
538-
cardType.add(getString(R.string.select_card))
539558
cardType.add(getString(R.string.american_express_pay_message))
540559
cardType.add(getString(R.string.mastercard_pay_message))
541560
cardType.add(getString(R.string.visa_pay_message))
@@ -606,13 +625,38 @@ class AttendeeFragment : Fragment() {
606625
rootView.attendeeScrollView.longSnackbar(getString(R.string.paypal_payment_not_available))
607626
false
608627
}
609-
getString(R.string.cheque), getString(R.string.on_site), getString(R.string.bank_transfer) -> {
610-
rootView.attendeeScrollView.longSnackbar(getString(R.string.offline_payment_message))
611-
false
612-
}
613628
else -> true
614629
}
615630

631+
private fun checkRequiredFields(): Boolean {
632+
val checkBasicInfo = rootView.firstName.checkEmpty() && rootView.lastName.checkEmpty() &&
633+
rootView.email.checkEmpty() && rootView.email.checkEmpty() && rootView.email.checkValidEmail()
634+
635+
var checkBillingInfo = true
636+
if (rootView.billingEnabledCheckbox.isChecked) {
637+
checkBillingInfo = rootView.company.checkEmpty() && rootView.company.checkEmpty() &&
638+
rootView.address.checkEmpty() && rootView.city.checkEmpty() && rootView.postalCode.checkEmpty()
639+
}
640+
641+
var checkStripeInfo = true
642+
if (totalAmount != 0F && rootView.paymentSelector.selectedItem.toString() == getString(R.string.stripe)) {
643+
checkStripeInfo = rootView.cardNumber.checkEmpty() && rootView.cvc.checkEmpty()
644+
}
645+
646+
return checkBasicInfo && checkBillingInfo && checkAttendeesInfo() && checkStripeInfo
647+
}
648+
649+
private fun checkAttendeesInfo(): Boolean {
650+
var valid = true
651+
for (pos in 0..attendeeRecyclerAdapter.itemCount) {
652+
val viewHolderItem = rootView.attendeeRecycler.findViewHolderForAdapterPosition(pos)
653+
if (viewHolderItem is AttendeeViewHolder) {
654+
if (!viewHolderItem.checkValidFields()) valid = false
655+
}
656+
}
657+
return valid
658+
}
659+
616660
private fun setupRegisterOrder() {
617661
rootView.register.setOnClickListener {
618662
if (!isNetworkConnected(context)) {
@@ -624,6 +668,8 @@ class AttendeeFragment : Fragment() {
624668
return@setOnClickListener
625669
}
626670

671+
if (!checkRequiredFields()) return@setOnClickListener
672+
627673
if (attendeeViewModel.totalAmount.value != 0F && !checkPaymentOptions()) return@setOnClickListener
628674

629675
val builder = AlertDialog.Builder(requireContext())
@@ -634,8 +680,9 @@ class AttendeeFragment : Fragment() {
634680

635681
if (attendeeViewModel.areAttendeeEmailsValid(attendees)) {
636682
val country = rootView.countryPicker.selectedItem.toString()
637-
val paymentOption = if (totalAmount != 0F) rootView.paymentSelector.selectedItem.toString()
638-
else getString(R.string.free)
683+
val paymentOption =
684+
if (totalAmount != 0F) getPaymentMode(rootView.paymentSelector.selectedItem.toString())
685+
else PAYMENT_MODE_FREE
639686
val company = rootView.company.text.toString()
640687
val city = rootView.city.text.toString()
641688
val taxId = rootView.taxId.text.toString()
@@ -676,6 +723,16 @@ class AttendeeFragment : Fragment() {
676723
})
677724
}
678725

726+
private fun getPaymentMode(paymentSelectedItem: String): String =
727+
when (paymentSelectedItem) {
728+
getString(R.string.cheque) -> PAYMENT_MODE_CHEQUE
729+
getString(R.string.bank_transfer) -> PAYMENT_MODE_BANK
730+
getString(R.string.stripe) -> PAYMENT_MODE_STRIPE
731+
getString(R.string.paypal) -> PAYMENT_MODE_PAYPAL
732+
getString(R.string.on_site) -> PAYMENT_MODE_ONSITE
733+
else -> PAYMENT_MODE_FREE
734+
}
735+
679736
private fun showTicketSoldOutDialog(show: Boolean) {
680737
if (show) {
681738
val builder = AlertDialog.Builder(requireContext())

app/src/main/java/org/fossasia/openevent/general/attendees/AttendeeViewHolder.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import org.fossasia.openevent.general.attendees.forms.CustomForm
1111
import org.fossasia.openevent.general.event.EventId
1212
import org.fossasia.openevent.general.ticket.Ticket
1313
import org.fossasia.openevent.general.ticket.TicketId
14+
import org.fossasia.openevent.general.utils.checkEmpty
15+
import org.fossasia.openevent.general.utils.checkValidEmail
16+
import org.fossasia.openevent.general.utils.setRequired
1417

1518
class AttendeeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
1619
private var identifierList = ArrayList<String>()
@@ -19,6 +22,9 @@ class AttendeeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
1922

2023
fun bind(attendee: Attendee, ticket: Ticket, customForm: List<CustomForm>, position: Int, eventId: Long) {
2124

25+
itemView.itemEmailLayout.setRequired()
26+
itemView.itemFirstNameLayout.setRequired()
27+
itemView.itemLastNameLayout.setRequired()
2228
itemView.attendeeItemCountry.setText(attendee.country)
2329
itemView.attendeeItemLastName.setText(attendee.lastname)
2430
itemView.attendeeItemEmail.setText(attendee.email)
@@ -57,6 +63,10 @@ class AttendeeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
5763
}
5864
}
5965

66+
fun checkValidFields(): Boolean =
67+
itemView.attendeeItemFirstName.checkEmpty() && itemView.attendeeItemLastName.checkEmpty() &&
68+
itemView.attendeeItemEmail.checkEmpty() && itemView.attendeeItemEmail.checkValidEmail()
69+
6070
private fun fillInformationSection(forms: List<CustomForm>, textWatcher: TextWatcher) {
6171
val layout = itemView.attendeeInformation
6272
for (form in forms) {

app/src/main/java/org/fossasia/openevent/general/attendees/AttendeeViewModel.kt

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ const val ORDER_STATUS_PENDING = "pending"
3131
const val ORDER_STATUS_COMPLETED = "completed"
3232
const val ORDER_STATUS_PLACED = "placed"
3333
const val ORDER_STATUS_CANCELLED = "cancelled"
34+
const val PAYMENT_MODE_FREE = "free"
35+
const val PAYMENT_MODE_BANK = "bank"
36+
const val PAYMENT_MODE_ONSITE = "onsite"
37+
const val PAYMENT_MODE_CHEQUE = "cheque"
38+
const val PAYMENT_MODE_PAYPAL = "paypal"
39+
const val PAYMENT_MODE_STRIPE = "stripe"
3440

3541
class AttendeeViewModel(
3642
private val attendeeService: AttendeeService,
@@ -67,7 +73,7 @@ class AttendeeViewModel(
6773
val attendees = ArrayList<Attendee>()
6874
private val attendeesForOrder = ArrayList<Attendee>()
6975
private val ticketsForOrder = ArrayList<Ticket>()
70-
private lateinit var paymentOption: String
76+
private var paymentModeForOrder: String = PAYMENT_MODE_FREE
7177
private var countryForOrder: String = ""
7278
private var companyForOrder: String = ""
7379
private var taxIdForOrder: String = ""
@@ -158,7 +164,7 @@ class AttendeeViewModel(
158164
address: String,
159165
city: String,
160166
postalCode: String,
161-
paymentOption: String
167+
paymentMode: String
162168
) {
163169
attendeesForOrder.clear()
164170
countryForOrder = country ?: ""
@@ -167,7 +173,7 @@ class AttendeeViewModel(
167173
addressForOrder = address
168174
cityForOrder = city
169175
postalCodeForOrder = postalCode
170-
this.paymentOption = paymentOption
176+
paymentModeForOrder = paymentMode
171177
var isAllDetailsFilled = true
172178
createAttendeeIterations = 0
173179
attendees.forEach {
@@ -214,14 +220,13 @@ class AttendeeViewModel(
214220
private fun createOrder() {
215221
val attendeeList = attendeesForOrder.map { AttendeeId(it.id) }.toList()
216222
val amount: Float = totalAmount.value ?: 0F
217-
var paymentMode: String? = paymentOption.toLowerCase()
218223
if (amount <= 0) {
219-
paymentMode = resource.getString(R.string.free)
224+
paymentModeForOrder = PAYMENT_MODE_FREE
220225
}
221226
val eventId = event.value?.id
222227
if (eventId != null) {
223-
var order = Order(id = getId(), paymentMode = paymentMode, status = ORDER_STATUS_PENDING, amount = amount,
224-
attendees = attendeeList, event = EventId(eventId))
228+
var order = Order(id = getId(), paymentMode = paymentModeForOrder, status = ORDER_STATUS_PENDING,
229+
amount = amount, attendees = attendeeList, event = EventId(eventId))
225230
if (billingEnabled) {
226231
order = order.copy(isBillingEnabled = true, company = companyForOrder, taxBusinessInfo = taxIdForOrder,
227232
address = addressForOrder, city = cityForOrder, zipcode = postalCodeForOrder, country = countryForOrder)
@@ -235,10 +240,17 @@ class AttendeeViewModel(
235240
}.subscribe({
236241
orderIdentifier = it.identifier.toString()
237242
Timber.d("Success placing order!")
238-
if (it.paymentMode == resource.getString(R.string.free)) {
239-
confirmOrder = ConfirmOrder(it.id.toString(), ORDER_STATUS_COMPLETED)
240-
confirmOrderStatus(it.identifier.toString(), confirmOrder)
241-
} else mutableMessage.value = resource.getString(R.string.order_success_message)
243+
when (it.paymentMode) {
244+
PAYMENT_MODE_FREE -> {
245+
confirmOrder = ConfirmOrder(it.id.toString(), ORDER_STATUS_COMPLETED)
246+
confirmOrderStatus(it.identifier.toString(), confirmOrder)
247+
}
248+
PAYMENT_MODE_CHEQUE, PAYMENT_MODE_BANK, PAYMENT_MODE_ONSITE -> {
249+
confirmOrder = ConfirmOrder(it.id.toString(), ORDER_STATUS_PLACED)
250+
confirmOrderStatus(it.identifier.toString(), confirmOrder)
251+
}
252+
else -> mutableMessage.value = resource.getString(R.string.order_success_message)
253+
}
242254
}, {
243255
mutableMessage.value = resource.getString(R.string.order_fail_message)
244256
Timber.d(it, "Failed creating Order")

app/src/main/java/org/fossasia/openevent/general/order/OrderCompletedFragment.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import androidx.fragment.app.Fragment
1313
import androidx.lifecycle.Observer
1414
import androidx.navigation.Navigation.findNavController
1515
import androidx.navigation.fragment.navArgs
16-
import kotlinx.android.synthetic.main.fragment_order.view.orderCoordinatorLayout
17-
import kotlinx.android.synthetic.main.fragment_order.view.add
18-
import kotlinx.android.synthetic.main.fragment_order.view.name
19-
import kotlinx.android.synthetic.main.fragment_order.view.share
20-
import kotlinx.android.synthetic.main.fragment_order.view.time
21-
import kotlinx.android.synthetic.main.fragment_order.view.view
16+
import kotlinx.android.synthetic.main.fragment_order_completed.view.orderCoordinatorLayout
17+
import kotlinx.android.synthetic.main.fragment_order_completed.view.add
18+
import kotlinx.android.synthetic.main.fragment_order_completed.view.name
19+
import kotlinx.android.synthetic.main.fragment_order_completed.view.share
20+
import kotlinx.android.synthetic.main.fragment_order_completed.view.time
21+
import kotlinx.android.synthetic.main.fragment_order_completed.view.view
2222
import org.fossasia.openevent.general.R
2323
import org.fossasia.openevent.general.event.Event
2424
import org.fossasia.openevent.general.event.EventUtils
@@ -40,7 +40,7 @@ class OrderCompletedFragment : Fragment() {
4040
container: ViewGroup?,
4141
savedInstanceState: Bundle?
4242
): View? {
43-
rootView = inflater.inflate(R.layout.fragment_order, container, false)
43+
rootView = inflater.inflate(R.layout.fragment_order_completed, container, false)
4444
setToolbar(activity)
4545
setHasOptionsMenu(true)
4646

0 commit comments

Comments
 (0)