fix and clean up

online_payment
Raz 7 months ago
parent b95c7acb83
commit f2f6e88d8a
  1. 32
      PadelClub.xcodeproj/project.pbxproj
  2. 6
      PadelClub/Data/CustomUser.swift
  3. 42
      PadelClub/Data/Gen/BaseTournament.swift
  4. 29
      PadelClub/Data/Gen/Tournament.json
  5. 4
      PadelClub/Data/Tournament.swift
  6. 5
      PadelClub/Utils/Network/RefundService.swift
  7. 68
      PadelClub/Utils/Network/StripeValidationService.swift
  8. 62
      PadelClub/Utils/Network/XlsToCsvService.swift
  9. 3
      PadelClub/Views/Navigation/Umpire/UmpireView.swift
  10. 2
      PadelClub/Views/Tournament/FileImportView.swift
  11. 117
      PadelClub/Views/Tournament/Screen/Components/RefundResultsView.swift
  12. 73
      PadelClub/Views/Tournament/Screen/Components/TournamentStatusView.swift
  13. 63
      PadelClub/Views/Tournament/Screen/RegistrationSetupView.swift
  14. 27
      PadelClub/Views/Tournament/TournamentInitView.swift

@ -423,7 +423,6 @@
FF4CBFE62C996C0600151637 /* MenuWarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */; }; FF4CBFE62C996C0600151637 /* MenuWarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */; };
FF4CBFE72C996C0600151637 /* TournamentBuildView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */; }; FF4CBFE72C996C0600151637 /* TournamentBuildView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */; };
FF4CBFE82C996C0600151637 /* TeamPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF967D0A2BAF3D4C00A9A3BD /* TeamPickerView.swift */; }; FF4CBFE82C996C0600151637 /* TeamPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF967D0A2BAF3D4C00A9A3BD /* TeamPickerView.swift */; };
FF4CBFE92C996C0600151637 /* CloudConvert.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7862BB0B7A2003A31F3 /* CloudConvert.swift */; };
FF4CBFEA2C996C0600151637 /* EventTournamentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF41832BF75ED7001B24CB /* EventTournamentsView.swift */; }; FF4CBFEA2C996C0600151637 /* EventTournamentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF41832BF75ED7001B24CB /* EventTournamentsView.swift */; };
FF4CBFEB2C996C0600151637 /* DisplayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */; }; FF4CBFEB2C996C0600151637 /* DisplayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */; };
FF4CBFEC2C996C0600151637 /* TournamentCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9268062BCE94D90080F940 /* TournamentCallView.swift */; }; FF4CBFEC2C996C0600151637 /* TournamentCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9268062BCE94D90080F940 /* TournamentCallView.swift */; };
@ -735,7 +734,6 @@
FF70FB652C90584900129CC2 /* MenuWarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */; }; FF70FB652C90584900129CC2 /* MenuWarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */; };
FF70FB662C90584900129CC2 /* TournamentBuildView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */; }; FF70FB662C90584900129CC2 /* TournamentBuildView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */; };
FF70FB672C90584900129CC2 /* TeamPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF967D0A2BAF3D4C00A9A3BD /* TeamPickerView.swift */; }; FF70FB672C90584900129CC2 /* TeamPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF967D0A2BAF3D4C00A9A3BD /* TeamPickerView.swift */; };
FF70FB682C90584900129CC2 /* CloudConvert.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7862BB0B7A2003A31F3 /* CloudConvert.swift */; };
FF70FB692C90584900129CC2 /* EventTournamentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF41832BF75ED7001B24CB /* EventTournamentsView.swift */; }; FF70FB692C90584900129CC2 /* EventTournamentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFBF41832BF75ED7001B24CB /* EventTournamentsView.swift */; };
FF70FB6A2C90584900129CC2 /* DisplayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */; }; FF70FB6A2C90584900129CC2 /* DisplayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */; };
FF70FB6B2C90584900129CC2 /* TournamentCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9268062BCE94D90080F940 /* TournamentCallView.swift */; }; FF70FB6B2C90584900129CC2 /* TournamentCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9268062BCE94D90080F940 /* TournamentCallView.swift */; };
@ -910,7 +908,6 @@
FFA252B62CDD2C6C0074E63F /* OngoingDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA252B42CDD2C630074E63F /* OngoingDestination.swift */; }; FFA252B62CDD2C6C0074E63F /* OngoingDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA252B42CDD2C630074E63F /* OngoingDestination.swift */; };
FFA252B72CDD2C6C0074E63F /* OngoingDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA252B42CDD2C630074E63F /* OngoingDestination.swift */; }; FFA252B72CDD2C6C0074E63F /* OngoingDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA252B42CDD2C630074E63F /* OngoingDestination.swift */; };
FFA6D7852BB0B795003A31F3 /* FileImportManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */; }; FFA6D7852BB0B795003A31F3 /* FileImportManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */; };
FFA6D7872BB0B7A2003A31F3 /* CloudConvert.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7862BB0B7A2003A31F3 /* CloudConvert.swift */; };
FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */; }; FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */; };
FFB378342D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */; }; FFB378342D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */; };
FFB378352D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */; }; FFB378352D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */; };
@ -979,6 +976,15 @@
FFE8B5BB2DA9896800BDE966 /* RefundService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BA2DA9896800BDE966 /* RefundService.swift */; }; FFE8B5BB2DA9896800BDE966 /* RefundService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BA2DA9896800BDE966 /* RefundService.swift */; };
FFE8B5BC2DA9896800BDE966 /* RefundService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BA2DA9896800BDE966 /* RefundService.swift */; }; FFE8B5BC2DA9896800BDE966 /* RefundService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BA2DA9896800BDE966 /* RefundService.swift */; };
FFE8B5BD2DA9896800BDE966 /* RefundService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BA2DA9896800BDE966 /* RefundService.swift */; }; FFE8B5BD2DA9896800BDE966 /* RefundService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BA2DA9896800BDE966 /* RefundService.swift */; };
FFE8B5BF2DAA325400BDE966 /* RefundResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BE2DAA325400BDE966 /* RefundResultsView.swift */; };
FFE8B5C02DAA325400BDE966 /* RefundResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BE2DAA325400BDE966 /* RefundResultsView.swift */; };
FFE8B5C12DAA325400BDE966 /* RefundResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5BE2DAA325400BDE966 /* RefundResultsView.swift */; };
FFE8B5C72DAA390900BDE966 /* StripeValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5C62DAA390000BDE966 /* StripeValidationService.swift */; };
FFE8B5C82DAA390900BDE966 /* StripeValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5C62DAA390000BDE966 /* StripeValidationService.swift */; };
FFE8B5C92DAA390900BDE966 /* StripeValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5C62DAA390000BDE966 /* StripeValidationService.swift */; };
FFE8B5CB2DAA42A000BDE966 /* XlsToCsvService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5CA2DAA429E00BDE966 /* XlsToCsvService.swift */; };
FFE8B5CC2DAA42A000BDE966 /* XlsToCsvService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5CA2DAA429E00BDE966 /* XlsToCsvService.swift */; };
FFE8B5CD2DAA42A000BDE966 /* XlsToCsvService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8B5CA2DAA429E00BDE966 /* XlsToCsvService.swift */; };
FFE8C2C02C7601E80046B243 /* ConfirmButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8C2BF2C7601E80046B243 /* ConfirmButtonView.swift */; }; FFE8C2C02C7601E80046B243 /* ConfirmButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFE8C2BF2C7601E80046B243 /* ConfirmButtonView.swift */; };
FFEF7F4E2BDE69130033D0F0 /* MenuWarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */; }; FFEF7F4E2BDE69130033D0F0 /* MenuWarningView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */; };
FFF0241E2BF48B15001F14B4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = FFF0241D2BF48B15001F14B4 /* Localizable.strings */; }; FFF0241E2BF48B15001F14B4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = FFF0241D2BF48B15001F14B4 /* Localizable.strings */; };
@ -1366,7 +1372,6 @@
FFA252B02CDD2C080074E63F /* OngoingContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OngoingContainerView.swift; sourceTree = "<group>"; }; FFA252B02CDD2C080074E63F /* OngoingContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OngoingContainerView.swift; sourceTree = "<group>"; };
FFA252B42CDD2C630074E63F /* OngoingDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OngoingDestination.swift; sourceTree = "<group>"; }; FFA252B42CDD2C630074E63F /* OngoingDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OngoingDestination.swift; sourceTree = "<group>"; };
FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileImportManager.swift; sourceTree = "<group>"; }; FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileImportManager.swift; sourceTree = "<group>"; };
FFA6D7862BB0B7A2003A31F3 /* CloudConvert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudConvert.swift; sourceTree = "<group>"; };
FFA6D78A2BB0BEB3003A31F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; FFA6D78A2BB0BEB3003A31F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentBroadcastRowView.swift; sourceTree = "<group>"; }; FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentBroadcastRowView.swift; sourceTree = "<group>"; };
FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchFormatGuideView.swift; sourceTree = "<group>"; }; FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchFormatGuideView.swift; sourceTree = "<group>"; };
@ -1419,6 +1424,9 @@
FFE8B5B22DA848D300BDE966 /* OnlineWaitingListFaqSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnlineWaitingListFaqSheetView.swift; sourceTree = "<group>"; }; FFE8B5B22DA848D300BDE966 /* OnlineWaitingListFaqSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnlineWaitingListFaqSheetView.swift; sourceTree = "<group>"; };
FFE8B5B62DA8763800BDE966 /* PaymentInfoSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentInfoSheetView.swift; sourceTree = "<group>"; }; FFE8B5B62DA8763800BDE966 /* PaymentInfoSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentInfoSheetView.swift; sourceTree = "<group>"; };
FFE8B5BA2DA9896800BDE966 /* RefundService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundService.swift; sourceTree = "<group>"; }; FFE8B5BA2DA9896800BDE966 /* RefundService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundService.swift; sourceTree = "<group>"; };
FFE8B5BE2DAA325400BDE966 /* RefundResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundResultsView.swift; sourceTree = "<group>"; };
FFE8B5C62DAA390000BDE966 /* StripeValidationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StripeValidationService.swift; sourceTree = "<group>"; };
FFE8B5CA2DAA429E00BDE966 /* XlsToCsvService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XlsToCsvService.swift; sourceTree = "<group>"; };
FFE8C2BF2C7601E80046B243 /* ConfirmButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmButtonView.swift; sourceTree = "<group>"; }; FFE8C2BF2C7601E80046B243 /* ConfirmButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmButtonView.swift; sourceTree = "<group>"; };
FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuWarningView.swift; sourceTree = "<group>"; }; FFEF7F4D2BDE69130033D0F0 /* MenuWarningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuWarningView.swift; sourceTree = "<group>"; };
FFF0241C2BF48B15001F14B4 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; }; FFF0241C2BF48B15001F14B4 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -2056,6 +2064,8 @@
FFC1E1092BAC2A77008D6F59 /* NetworkFederalService.swift */, FFC1E1092BAC2A77008D6F59 /* NetworkFederalService.swift */,
FF6EC9052B947A1000EA7F5A /* NetworkManagerError.swift */, FF6EC9052B947A1000EA7F5A /* NetworkManagerError.swift */,
FFE8B5BA2DA9896800BDE966 /* RefundService.swift */, FFE8B5BA2DA9896800BDE966 /* RefundService.swift */,
FFE8B5C62DAA390000BDE966 /* StripeValidationService.swift */,
FFE8B5CA2DAA429E00BDE966 /* XlsToCsvService.swift */,
); );
path = Network; path = Network;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2075,6 +2085,7 @@
FF025AE42BD0EBB800A86CF8 /* TournamentGeneralSettingsView.swift */, FF025AE42BD0EBB800A86CF8 /* TournamentGeneralSettingsView.swift */,
FF4623CA2D1340D200CB57B5 /* TournamentCategorySettingsView.swift */, FF4623CA2D1340D200CB57B5 /* TournamentCategorySettingsView.swift */,
FF6087E92BE25EF1004E1E47 /* TournamentStatusView.swift */, FF6087E92BE25EF1004E1E47 /* TournamentStatusView.swift */,
FFE8B5BE2DAA325400BDE966 /* RefundResultsView.swift */,
FFCF76062C3BE9BC006C8C3D /* CloseDatePicker.swift */, FFCF76062C3BE9BC006C8C3D /* CloseDatePicker.swift */,
); );
path = Components; path = Components;
@ -2242,7 +2253,6 @@
children = ( children = (
FF6EC9072B947A1E00EA7F5A /* Network */, FF6EC9072B947A1E00EA7F5A /* Network */,
FF8E1CE52C006E0200184680 /* Alphabet.swift */, FF8E1CE52C006E0200184680 /* Alphabet.swift */,
FFA6D7862BB0B7A2003A31F3 /* CloudConvert.swift */,
FF92680A2BCEE3E10080F940 /* ContactManager.swift */, FF92680A2BCEE3E10080F940 /* ContactManager.swift */,
FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */, FF1DC55A2BAB80C400FD8220 /* DisplayContext.swift */,
FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */, FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */,
@ -2634,6 +2644,7 @@
FFE2D2E22C231BEE00D0C7BE /* SupportButtonView.swift in Sources */, FFE2D2E22C231BEE00D0C7BE /* SupportButtonView.swift in Sources */,
FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */, FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */,
FF025ADF2BD0CE0A00A86CF8 /* TeamWeightView.swift in Sources */, FF025ADF2BD0CE0A00A86CF8 /* TeamWeightView.swift in Sources */,
FFE8B5C12DAA325400BDE966 /* RefundResultsView.swift in Sources */,
FF9268012BCE94920080F940 /* SeedsCallingView.swift in Sources */, FF9268012BCE94920080F940 /* SeedsCallingView.swift in Sources */,
FF9268092BCEDC2C0080F940 /* CallView.swift in Sources */, FF9268092BCEDC2C0080F940 /* CallView.swift in Sources */,
FF5D0D742BB41DF8005CB568 /* Color+Extensions.swift in Sources */, FF5D0D742BB41DF8005CB568 /* Color+Extensions.swift in Sources */,
@ -2740,6 +2751,7 @@
FF8F263D2BAD627A00650388 /* TournamentConfiguratorView.swift in Sources */, FF8F263D2BAD627A00650388 /* TournamentConfiguratorView.swift in Sources */,
FFC1E10C2BAC7FB0008D6F59 /* ClubImportView.swift in Sources */, FFC1E10C2BAC7FB0008D6F59 /* ClubImportView.swift in Sources */,
FF558C632C6CDD020071F9AE /* UnderlineView.swift in Sources */, FF558C632C6CDD020071F9AE /* UnderlineView.swift in Sources */,
FFE8B5CD2DAA42A000BDE966 /* XlsToCsvService.swift in Sources */,
FF3B60A32BC49BBC008C2E66 /* MatchScheduler.swift in Sources */, FF3B60A32BC49BBC008C2E66 /* MatchScheduler.swift in Sources */,
FF11627A2BCF8109000C4809 /* CallMessageCustomizationView.swift in Sources */, FF11627A2BCF8109000C4809 /* CallMessageCustomizationView.swift in Sources */,
FF6087EA2BE25EF1004E1E47 /* TournamentStatusView.swift in Sources */, FF6087EA2BE25EF1004E1E47 /* TournamentStatusView.swift in Sources */,
@ -2802,7 +2814,6 @@
FFEF7F4E2BDE69130033D0F0 /* MenuWarningView.swift in Sources */, FFEF7F4E2BDE69130033D0F0 /* MenuWarningView.swift in Sources */,
FF1F4B6D2BF9E60B000B4573 /* TournamentBuildView.swift in Sources */, FF1F4B6D2BF9E60B000B4573 /* TournamentBuildView.swift in Sources */,
FF967D0B2BAF3D4C00A9A3BD /* TeamPickerView.swift in Sources */, FF967D0B2BAF3D4C00A9A3BD /* TeamPickerView.swift in Sources */,
FFA6D7872BB0B7A2003A31F3 /* CloudConvert.swift in Sources */,
FFBF41842BF75ED7001B24CB /* EventTournamentsView.swift in Sources */, FFBF41842BF75ED7001B24CB /* EventTournamentsView.swift in Sources */,
FF1DC55B2BAB80C400FD8220 /* DisplayContext.swift in Sources */, FF1DC55B2BAB80C400FD8220 /* DisplayContext.swift in Sources */,
FFB39B352D8E8B05008E0C89 /* MatchSpot.swift in Sources */, FFB39B352D8E8B05008E0C89 /* MatchSpot.swift in Sources */,
@ -2851,6 +2862,7 @@
FFF964532BC262B000EEF017 /* PlanningSettingsView.swift in Sources */, FFF964532BC262B000EEF017 /* PlanningSettingsView.swift in Sources */,
FFF527D62BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift in Sources */, FFF527D62BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift in Sources */,
FFC91AF92BD6A09100B29808 /* FortuneWheelView.swift in Sources */, FFC91AF92BD6A09100B29808 /* FortuneWheelView.swift in Sources */,
FFE8B5C82DAA390900BDE966 /* StripeValidationService.swift in Sources */,
FFF8ACD62B923960008466FA /* URL+Extensions.swift in Sources */, FFF8ACD62B923960008466FA /* URL+Extensions.swift in Sources */,
C493B37E2C10AD3600862481 /* LoadingViewModifier.swift in Sources */, C493B37E2C10AD3600862481 /* LoadingViewModifier.swift in Sources */,
FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */, FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */,
@ -3056,6 +3068,7 @@
FF4CBFAD2C996C0600151637 /* RoundScheduleEditorView.swift in Sources */, FF4CBFAD2C996C0600151637 /* RoundScheduleEditorView.swift in Sources */,
FF4CBFAE2C996C0600151637 /* EventListView.swift in Sources */, FF4CBFAE2C996C0600151637 /* EventListView.swift in Sources */,
FF4CBFAF2C996C0600151637 /* TournamentConfiguratorView.swift in Sources */, FF4CBFAF2C996C0600151637 /* TournamentConfiguratorView.swift in Sources */,
FFE8B5C72DAA390900BDE966 /* StripeValidationService.swift in Sources */,
FF4CBFB02C996C0600151637 /* ClubImportView.swift in Sources */, FF4CBFB02C996C0600151637 /* ClubImportView.swift in Sources */,
FF4CBFB12C996C0600151637 /* UnderlineView.swift in Sources */, FF4CBFB12C996C0600151637 /* UnderlineView.swift in Sources */,
FF4CBFB22C996C0600151637 /* MatchScheduler.swift in Sources */, FF4CBFB22C996C0600151637 /* MatchScheduler.swift in Sources */,
@ -3121,7 +3134,6 @@
FF4CBFE62C996C0600151637 /* MenuWarningView.swift in Sources */, FF4CBFE62C996C0600151637 /* MenuWarningView.swift in Sources */,
FF4CBFE72C996C0600151637 /* TournamentBuildView.swift in Sources */, FF4CBFE72C996C0600151637 /* TournamentBuildView.swift in Sources */,
FF4CBFE82C996C0600151637 /* TeamPickerView.swift in Sources */, FF4CBFE82C996C0600151637 /* TeamPickerView.swift in Sources */,
FF4CBFE92C996C0600151637 /* CloudConvert.swift in Sources */,
FF4CBFEA2C996C0600151637 /* EventTournamentsView.swift in Sources */, FF4CBFEA2C996C0600151637 /* EventTournamentsView.swift in Sources */,
FF4CBFEB2C996C0600151637 /* DisplayContext.swift in Sources */, FF4CBFEB2C996C0600151637 /* DisplayContext.swift in Sources */,
FFB39B342D8E8B05008E0C89 /* MatchSpot.swift in Sources */, FFB39B342D8E8B05008E0C89 /* MatchSpot.swift in Sources */,
@ -3130,6 +3142,7 @@
FF4CBFED2C996C0600151637 /* LoserRoundsView.swift in Sources */, FF4CBFED2C996C0600151637 /* LoserRoundsView.swift in Sources */,
FF4CBFEE2C996C0600151637 /* GroupStagesView.swift in Sources */, FF4CBFEE2C996C0600151637 /* GroupStagesView.swift in Sources */,
FF4CBFEF2C996C0600151637 /* PadelClubView.swift in Sources */, FF4CBFEF2C996C0600151637 /* PadelClubView.swift in Sources */,
FFE8B5CC2DAA42A000BDE966 /* XlsToCsvService.swift in Sources */,
FF3A73F52D37C34D007E3032 /* RegistrationInfoSheetView.swift in Sources */, FF3A73F52D37C34D007E3032 /* RegistrationInfoSheetView.swift in Sources */,
FF4CBFF02C996C0600151637 /* URLs.swift in Sources */, FF4CBFF02C996C0600151637 /* URLs.swift in Sources */,
FF4CBFF12C996C0600151637 /* MatchDescriptor.swift in Sources */, FF4CBFF12C996C0600151637 /* MatchDescriptor.swift in Sources */,
@ -3194,6 +3207,7 @@
FF4CC0212C996C0600151637 /* GroupStageScheduleEditorView.swift in Sources */, FF4CC0212C996C0600151637 /* GroupStageScheduleEditorView.swift in Sources */,
FF4CC0222C996C0600151637 /* EventView.swift in Sources */, FF4CC0222C996C0600151637 /* EventView.swift in Sources */,
FF4CC0232C996C0600151637 /* LoginView.swift in Sources */, FF4CC0232C996C0600151637 /* LoginView.swift in Sources */,
FFE8B5BF2DAA325400BDE966 /* RefundResultsView.swift in Sources */,
FF4CC0242C996C0600151637 /* Court.swift in Sources */, FF4CC0242C996C0600151637 /* Court.swift in Sources */,
FF4CC0252C996C0600151637 /* Labels.swift in Sources */, FF4CC0252C996C0600151637 /* Labels.swift in Sources */,
FF4CC0262C996C0600151637 /* CopyPasteButtonView.swift in Sources */, FF4CC0262C996C0600151637 /* CopyPasteButtonView.swift in Sources */,
@ -3353,6 +3367,7 @@
FF70FB2C2C90584900129CC2 /* RoundScheduleEditorView.swift in Sources */, FF70FB2C2C90584900129CC2 /* RoundScheduleEditorView.swift in Sources */,
FF70FB2D2C90584900129CC2 /* EventListView.swift in Sources */, FF70FB2D2C90584900129CC2 /* EventListView.swift in Sources */,
FF70FB2E2C90584900129CC2 /* TournamentConfiguratorView.swift in Sources */, FF70FB2E2C90584900129CC2 /* TournamentConfiguratorView.swift in Sources */,
FFE8B5C92DAA390900BDE966 /* StripeValidationService.swift in Sources */,
FF70FB2F2C90584900129CC2 /* ClubImportView.swift in Sources */, FF70FB2F2C90584900129CC2 /* ClubImportView.swift in Sources */,
FF70FB302C90584900129CC2 /* UnderlineView.swift in Sources */, FF70FB302C90584900129CC2 /* UnderlineView.swift in Sources */,
FF70FB312C90584900129CC2 /* MatchScheduler.swift in Sources */, FF70FB312C90584900129CC2 /* MatchScheduler.swift in Sources */,
@ -3418,7 +3433,6 @@
FF70FB652C90584900129CC2 /* MenuWarningView.swift in Sources */, FF70FB652C90584900129CC2 /* MenuWarningView.swift in Sources */,
FF70FB662C90584900129CC2 /* TournamentBuildView.swift in Sources */, FF70FB662C90584900129CC2 /* TournamentBuildView.swift in Sources */,
FF70FB672C90584900129CC2 /* TeamPickerView.swift in Sources */, FF70FB672C90584900129CC2 /* TeamPickerView.swift in Sources */,
FF70FB682C90584900129CC2 /* CloudConvert.swift in Sources */,
FF70FB692C90584900129CC2 /* EventTournamentsView.swift in Sources */, FF70FB692C90584900129CC2 /* EventTournamentsView.swift in Sources */,
FF70FB6A2C90584900129CC2 /* DisplayContext.swift in Sources */, FF70FB6A2C90584900129CC2 /* DisplayContext.swift in Sources */,
FFB39B362D8E8B05008E0C89 /* MatchSpot.swift in Sources */, FFB39B362D8E8B05008E0C89 /* MatchSpot.swift in Sources */,
@ -3427,6 +3441,7 @@
FF70FB6C2C90584900129CC2 /* LoserRoundsView.swift in Sources */, FF70FB6C2C90584900129CC2 /* LoserRoundsView.swift in Sources */,
FF70FB6D2C90584900129CC2 /* GroupStagesView.swift in Sources */, FF70FB6D2C90584900129CC2 /* GroupStagesView.swift in Sources */,
FF70FB6E2C90584900129CC2 /* PadelClubView.swift in Sources */, FF70FB6E2C90584900129CC2 /* PadelClubView.swift in Sources */,
FFE8B5CB2DAA42A000BDE966 /* XlsToCsvService.swift in Sources */,
FF3A73F42D37C34D007E3032 /* RegistrationInfoSheetView.swift in Sources */, FF3A73F42D37C34D007E3032 /* RegistrationInfoSheetView.swift in Sources */,
FF70FB6F2C90584900129CC2 /* URLs.swift in Sources */, FF70FB6F2C90584900129CC2 /* URLs.swift in Sources */,
FF70FB702C90584900129CC2 /* MatchDescriptor.swift in Sources */, FF70FB702C90584900129CC2 /* MatchDescriptor.swift in Sources */,
@ -3491,6 +3506,7 @@
FF70FBA02C90584900129CC2 /* GroupStageScheduleEditorView.swift in Sources */, FF70FBA02C90584900129CC2 /* GroupStageScheduleEditorView.swift in Sources */,
FF70FBA12C90584900129CC2 /* EventView.swift in Sources */, FF70FBA12C90584900129CC2 /* EventView.swift in Sources */,
FF70FBA22C90584900129CC2 /* LoginView.swift in Sources */, FF70FBA22C90584900129CC2 /* LoginView.swift in Sources */,
FFE8B5C02DAA325400BDE966 /* RefundResultsView.swift in Sources */,
FF70FBA32C90584900129CC2 /* Court.swift in Sources */, FF70FBA32C90584900129CC2 /* Court.swift in Sources */,
FF70FBA42C90584900129CC2 /* Labels.swift in Sources */, FF70FBA42C90584900129CC2 /* Labels.swift in Sources */,
FF70FBA52C90584900129CC2 /* CopyPasteButtonView.swift in Sources */, FF70FBA52C90584900129CC2 /* CopyPasteButtonView.swift in Sources */,

@ -64,12 +64,12 @@ enum RegistrationPaymentMode: Int, Codable {
} }
} }
func sample(entryFee: Double) -> String? { func sample(entryFee: Double) -> String {
if let fee = self.fee() { if let fee = self.fee() {
let feeAmount = entryFee * fee let feeAmount = entryFee * fee
return String(format: "%.2f", feeAmount) return String(format: "%.2f", feeAmount)
} else { } else {
return nil return "0"
} }
} }

@ -23,20 +23,20 @@ class BaseTournament: SyncedModelObject, SyncedStorable {
var roundFormat: MatchFormat? = nil var roundFormat: MatchFormat? = nil
var loserRoundFormat: MatchFormat? = nil var loserRoundFormat: MatchFormat? = nil
var groupStageSortMode: GroupStageOrderingMode = GroupStageOrderingMode.snake var groupStageSortMode: GroupStageOrderingMode = GroupStageOrderingMode.snake
var groupStageCount: Int = 0 var groupStageCount: Int = 4
var rankSourceDate: Date? = nil var rankSourceDate: Date? = nil
var dayDuration: Int = 0 var dayDuration: Int = 1
var teamCount: Int = 0 var teamCount: Int = 24
var teamSorting: TeamSortingType = TeamSortingType.inscriptionDate var teamSorting: TeamSortingType = TeamSortingType.inscriptionDate
var federalCategory: TournamentCategory = TournamentCategory.men var federalCategory: TournamentCategory = TournamentCategory.men
var federalLevelCategory: TournamentLevel = TournamentLevel.unlisted var federalLevelCategory: TournamentLevel = TournamentLevel.p100
var federalAgeCategory: FederalTournamentAge = FederalTournamentAge.unlisted var federalAgeCategory: FederalTournamentAge = FederalTournamentAge.senior
var closedRegistrationDate: Date? = nil var closedRegistrationDate: Date? = nil
var groupStageAdditionalQualified: Int = 0 var groupStageAdditionalQualified: Int = 0
var courtCount: Int = 2 var courtCount: Int = 2
var prioritizeClubMembers: Bool = false var prioritizeClubMembers: Bool = false
var qualifiedPerGroupStage: Int = 0 var qualifiedPerGroupStage: Int = 1
var teamsPerGroupStage: Int = 0 var teamsPerGroupStage: Int = 4
var entryFee: Double? = nil var entryFee: Double? = nil
var payment: TournamentPayment? = nil var payment: TournamentPayment? = nil
var additionalEstimationDuration: Int = 0 var additionalEstimationDuration: Int = 0
@ -92,20 +92,20 @@ class BaseTournament: SyncedModelObject, SyncedStorable {
roundFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil,
loserRoundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil,
groupStageSortMode: GroupStageOrderingMode = GroupStageOrderingMode.snake, groupStageSortMode: GroupStageOrderingMode = GroupStageOrderingMode.snake,
groupStageCount: Int = 0, groupStageCount: Int = 4,
rankSourceDate: Date? = nil, rankSourceDate: Date? = nil,
dayDuration: Int = 0, dayDuration: Int = 1,
teamCount: Int = 0, teamCount: Int = 24,
teamSorting: TeamSortingType = TeamSortingType.inscriptionDate, teamSorting: TeamSortingType = TeamSortingType.inscriptionDate,
federalCategory: TournamentCategory = TournamentCategory.men, federalCategory: TournamentCategory = TournamentCategory.men,
federalLevelCategory: TournamentLevel = TournamentLevel.unlisted, federalLevelCategory: TournamentLevel = TournamentLevel.p100,
federalAgeCategory: FederalTournamentAge = FederalTournamentAge.unlisted, federalAgeCategory: FederalTournamentAge = FederalTournamentAge.senior,
closedRegistrationDate: Date? = nil, closedRegistrationDate: Date? = nil,
groupStageAdditionalQualified: Int = 0, groupStageAdditionalQualified: Int = 0,
courtCount: Int = 2, courtCount: Int = 2,
prioritizeClubMembers: Bool = false, prioritizeClubMembers: Bool = false,
qualifiedPerGroupStage: Int = 0, qualifiedPerGroupStage: Int = 1,
teamsPerGroupStage: Int = 0, teamsPerGroupStage: Int = 4,
entryFee: Double? = nil, entryFee: Double? = nil,
payment: TournamentPayment? = nil, payment: TournamentPayment? = nil,
additionalEstimationDuration: Int = 0, additionalEstimationDuration: Int = 0,
@ -374,20 +374,20 @@ class BaseTournament: SyncedModelObject, SyncedStorable {
self.roundFormat = try container.decodeIfPresent(MatchFormat.self, forKey: ._roundFormat) ?? nil self.roundFormat = try container.decodeIfPresent(MatchFormat.self, forKey: ._roundFormat) ?? nil
self.loserRoundFormat = try container.decodeIfPresent(MatchFormat.self, forKey: ._loserRoundFormat) ?? nil self.loserRoundFormat = try container.decodeIfPresent(MatchFormat.self, forKey: ._loserRoundFormat) ?? nil
self.groupStageSortMode = try container.decodeIfPresent(GroupStageOrderingMode.self, forKey: ._groupStageSortMode) ?? GroupStageOrderingMode.snake self.groupStageSortMode = try container.decodeIfPresent(GroupStageOrderingMode.self, forKey: ._groupStageSortMode) ?? GroupStageOrderingMode.snake
self.groupStageCount = try container.decodeIfPresent(Int.self, forKey: ._groupStageCount) ?? 0 self.groupStageCount = try container.decodeIfPresent(Int.self, forKey: ._groupStageCount) ?? 4
self.rankSourceDate = try container.decodeIfPresent(Date.self, forKey: ._rankSourceDate) ?? nil self.rankSourceDate = try container.decodeIfPresent(Date.self, forKey: ._rankSourceDate) ?? nil
self.dayDuration = try container.decodeIfPresent(Int.self, forKey: ._dayDuration) ?? 0 self.dayDuration = try container.decodeIfPresent(Int.self, forKey: ._dayDuration) ?? 1
self.teamCount = try container.decodeIfPresent(Int.self, forKey: ._teamCount) ?? 0 self.teamCount = try container.decodeIfPresent(Int.self, forKey: ._teamCount) ?? 24
self.teamSorting = try container.decodeIfPresent(TeamSortingType.self, forKey: ._teamSorting) ?? TeamSortingType.inscriptionDate self.teamSorting = try container.decodeIfPresent(TeamSortingType.self, forKey: ._teamSorting) ?? TeamSortingType.inscriptionDate
self.federalCategory = try container.decodeIfPresent(TournamentCategory.self, forKey: ._federalCategory) ?? TournamentCategory.men self.federalCategory = try container.decodeIfPresent(TournamentCategory.self, forKey: ._federalCategory) ?? TournamentCategory.men
self.federalLevelCategory = try container.decodeIfPresent(TournamentLevel.self, forKey: ._federalLevelCategory) ?? TournamentLevel.unlisted self.federalLevelCategory = try container.decodeIfPresent(TournamentLevel.self, forKey: ._federalLevelCategory) ?? TournamentLevel.p100
self.federalAgeCategory = try container.decodeIfPresent(FederalTournamentAge.self, forKey: ._federalAgeCategory) ?? FederalTournamentAge.unlisted self.federalAgeCategory = try container.decodeIfPresent(FederalTournamentAge.self, forKey: ._federalAgeCategory) ?? FederalTournamentAge.senior
self.closedRegistrationDate = try container.decodeIfPresent(Date.self, forKey: ._closedRegistrationDate) ?? nil self.closedRegistrationDate = try container.decodeIfPresent(Date.self, forKey: ._closedRegistrationDate) ?? nil
self.groupStageAdditionalQualified = try container.decodeIfPresent(Int.self, forKey: ._groupStageAdditionalQualified) ?? 0 self.groupStageAdditionalQualified = try container.decodeIfPresent(Int.self, forKey: ._groupStageAdditionalQualified) ?? 0
self.courtCount = try container.decodeIfPresent(Int.self, forKey: ._courtCount) ?? 2 self.courtCount = try container.decodeIfPresent(Int.self, forKey: ._courtCount) ?? 2
self.prioritizeClubMembers = try container.decodeIfPresent(Bool.self, forKey: ._prioritizeClubMembers) ?? false self.prioritizeClubMembers = try container.decodeIfPresent(Bool.self, forKey: ._prioritizeClubMembers) ?? false
self.qualifiedPerGroupStage = try container.decodeIfPresent(Int.self, forKey: ._qualifiedPerGroupStage) ?? 0 self.qualifiedPerGroupStage = try container.decodeIfPresent(Int.self, forKey: ._qualifiedPerGroupStage) ?? 1
self.teamsPerGroupStage = try container.decodeIfPresent(Int.self, forKey: ._teamsPerGroupStage) ?? 0 self.teamsPerGroupStage = try container.decodeIfPresent(Int.self, forKey: ._teamsPerGroupStage) ?? 4
self.entryFee = try container.decodeIfPresent(Double.self, forKey: ._entryFee) ?? nil self.entryFee = try container.decodeIfPresent(Double.self, forKey: ._entryFee) ?? nil
self.payment = try Self._decodePayment(container: container) self.payment = try Self._decodePayment(container: container)
self.additionalEstimationDuration = try container.decodeIfPresent(Int.self, forKey: ._additionalEstimationDuration) ?? 0 self.additionalEstimationDuration = try container.decodeIfPresent(Int.self, forKey: ._additionalEstimationDuration) ?? 0

@ -66,7 +66,8 @@
}, },
{ {
"name": "groupStageCount", "name": "groupStageCount",
"type": "Int" "type": "Int",
"defaultValue": "4"
}, },
{ {
"name": "rankSourceDate", "name": "rankSourceDate",
@ -75,11 +76,13 @@
}, },
{ {
"name": "dayDuration", "name": "dayDuration",
"type": "Int" "type": "Int",
"defaultValue": "1"
}, },
{ {
"name": "teamCount", "name": "teamCount",
"type": "Int" "type": "Int",
"defaultValue": "24"
}, },
{ {
"name": "teamSorting", "name": "teamSorting",
@ -94,12 +97,12 @@
{ {
"name": "federalLevelCategory", "name": "federalLevelCategory",
"type": "TournamentLevel", "type": "TournamentLevel",
"defaultValue": "TournamentLevel.unlisted" "defaultValue": "TournamentLevel.p100"
}, },
{ {
"name": "federalAgeCategory", "name": "federalAgeCategory",
"type": "FederalTournamentAge", "type": "FederalTournamentAge",
"defaultValue": "FederalTournamentAge.unlisted" "defaultValue": "FederalTournamentAge.senior"
}, },
{ {
"name": "closedRegistrationDate", "name": "closedRegistrationDate",
@ -108,7 +111,8 @@
}, },
{ {
"name": "groupStageAdditionalQualified", "name": "groupStageAdditionalQualified",
"type": "Int" "type": "Int",
"defaultValue": "0"
}, },
{ {
"name": "courtCount", "name": "courtCount",
@ -117,15 +121,18 @@
}, },
{ {
"name": "prioritizeClubMembers", "name": "prioritizeClubMembers",
"type": "Bool" "type": "Bool",
"defaultValue": "false"
}, },
{ {
"name": "qualifiedPerGroupStage", "name": "qualifiedPerGroupStage",
"type": "Int" "type": "Int",
"defaultValue": "1"
}, },
{ {
"name": "teamsPerGroupStage", "name": "teamsPerGroupStage",
"type": "Int" "type": "Int",
"defaultValue": "4"
}, },
{ {
"name": "entryFee", "name": "entryFee",
@ -255,12 +262,12 @@
{ {
"name": "minimumPlayerPerTeam", "name": "minimumPlayerPerTeam",
"type": "Int", "type": "Int",
"defaultValue": 2 "defaultValue": "2"
}, },
{ {
"name": "maximumPlayerPerTeam", "name": "maximumPlayerPerTeam",
"type": "Int", "type": "Int",
"defaultValue": 2 "defaultValue": "2"
}, },
{ {
"name": "information", "name": "information",

@ -2383,10 +2383,6 @@ defer {
unsortedTeams().filter({ $0.hasPaidOnline() }) unsortedTeams().filter({ $0.hasPaidOnline() })
} }
func refundTeams() {
}
func shouldWarnOnlineRegistrationUpdates() -> Bool { func shouldWarnOnlineRegistrationUpdates() -> Bool {
enableOnlineRegistration && onlineTeams().isEmpty == false && hasEnded() == false && hasStarted() == false enableOnlineRegistration && onlineTeams().isEmpty == false && hasEnded() == false && hasStarted() == false
} }

@ -42,3 +42,8 @@ enum RefundError: Error {
case unauthorized case unauthorized
case unknown case unknown
} }
struct RefundResult {
let team: TeamRegistration
let response: Result<RefundResponse, Error>
}

@ -0,0 +1,68 @@
//
// StripeValidationService.swift
// PadelClub
//
// Created by razmig on 12/04/2025.
//
import Foundation
import LeStorage
class StripeValidationService {
static func validateStripeAccountID(_ accountID: String) async throws -> ValidationResponse {
let service = try StoreCenter.main.service()
var urlRequest = try service._baseRequest(servicePath: "validate-stripe-account/", method: .post, requiresToken: true)
let body = ["account_id": accountID]
urlRequest.httpBody = try JSONEncoder().encode(body)
do {
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let httpResponse = response as? HTTPURLResponse else {
throw ValidationError.invalidResponse
}
switch httpResponse.statusCode {
case 200...299:
let decodedResponse = try JSONDecoder().decode(ValidationResponse.self, from: data)
return decodedResponse
case 400:
// Handle bad request
let errorResponse = try JSONDecoder().decode(ValidationResponse.self, from: data)
return errorResponse
case 403:
// Handle permission error
let errorResponse = try JSONDecoder().decode(ValidationResponse.self, from: data)
return errorResponse
default:
throw ValidationError.invalidResponse
}
} catch let error as ValidationError {
throw error
} catch {
throw ValidationError.networkError(error)
}
}
}
struct ValidationResponse: Codable {
let valid: Bool
let account: AccountDetails?
let error: String?
}
struct AccountDetails: Codable {
let id: String
enum CodingKeys: String, CodingKey {
case id
}
}
enum ValidationError: Error {
case invalidResponse
case networkError(Error)
case invalidData
}

@ -1,44 +1,18 @@
// //
// CloudConvert.swift // XlsToCsvService.swift
// Padel Tournament // PadelClub
// //
// Created by Razmig Sarkissian on 14/09/2023. // Created by razmig on 12/04/2025.
// //
import Foundation import Foundation
import LeStorage
class CloudConvert { class XlsToCsvService {
enum CloudConvertionError: LocalizedError { static func exportToCsv(url: URL) async throws -> String {
case unknownError let service = try StoreCenter.main.service()
case serviceError(ErrorResponse) var request = try service._baseRequest(servicePath: "xls-to-csv/", method: .post, requiresToken: true)
case urlNotFound(String)
var errorDescription: String? {
switch self {
case .unknownError:
return "Erreur"
case .serviceError(let errorResponse):
return errorResponse.error
case .urlNotFound(let url):
return "L'URL [\(url)] n'est pas valide"
}
}
}
static let manager = CloudConvert()
func uploadFile(_ url: URL) async throws -> String {
return try await createJob(url)
}
func createJob(_ url: URL) async throws -> String {
let apiPath = "https://\(URLs.activationHost.rawValue)/utils/xls-to-csv/"
guard let taskURL = URL(string: apiPath) else {
throw CloudConvertionError.urlNotFound(apiPath)
}
var request: URLRequest = URLRequest(url: taskURL)
request.httpMethod = "POST"
// Create the boundary string for multipart/form-data // Create the boundary string for multipart/form-data
let boundary = UUID().uuidString let boundary = UUID().uuidString
@ -81,13 +55,29 @@ class CloudConvert {
return responseString return responseString
} else { } else {
let error = ErrorResponse(code: 1, status: "Encodage", error: "Encodage des données de classement invalide") let error = ErrorResponse(code: 1, status: "Encodage", error: "Encodage des données de classement invalide")
throw CloudConvertionError.serviceError(error) throw ConvertionError.serviceError(error)
} }
} }
} }
// MARK: - ErrorResponse
struct ErrorResponse: Decodable { struct ErrorResponse: Decodable {
let code: Int let code: Int
let status, error: String let status, error: String
} }
enum ConvertionError: LocalizedError {
case unknownError
case serviceError(ErrorResponse)
case urlNotFound(String)
var errorDescription: String? {
switch self {
case .unknownError:
return "Erreur"
case .serviceError(let errorResponse):
return errorResponse.error
case .urlNotFound(let url):
return "L'URL [\(url)] n'est pas valide"
}
}
}

@ -142,6 +142,7 @@ struct UmpireView: View {
// } // }
// } // }
// //
if StoreCenter.main.isAuthenticated {
_customUmpireView() _customUmpireView()
Section { Section {
@ -160,7 +161,7 @@ struct UmpireView: View {
} footer: { } footer: {
Text("Ces informations ne seront pas affichées sur la page d'information des tournois sur Padel Club et dans les emails envoyés automatiquement au regard des inscriptions en lignes.") Text("Ces informations ne seront pas affichées sur la page d'information des tournois sur Padel Club et dans les emails envoyés automatiquement au regard des inscriptions en lignes.")
} }
}
Section { Section {
@Bindable var user = dataStore.user @Bindable var user = dataStore.user

@ -421,7 +421,7 @@ struct FileImportView: View {
do { do {
if selectedFile.lastPathComponent.hasSuffix("xls") || selectedFile.lastPathComponent.hasSuffix("xlsx") { if selectedFile.lastPathComponent.hasSuffix("xls") || selectedFile.lastPathComponent.hasSuffix("xlsx") {
convertingFile = true convertingFile = true
fileContent = try await CloudConvert.manager.uploadFile(selectedFile) fileContent = try await XlsToCsvService.exportToCsv(url: selectedFile)
convertingFile = false convertingFile = false
} else { } else {
fileContent = try String(contentsOf: selectedFile) fileContent = try String(contentsOf: selectedFile)

@ -0,0 +1,117 @@
//
// RefundResultsView.swift
// PadelClub
//
// Created by razmig on 12/04/2025.
//
import SwiftUI
import LeStorage
struct RefundResultsView: View {
@Binding var results: [RefundResult]
let tournament: Tournament
@Environment(\.dismiss) private var dismiss
@State private var processingRetry: Set<String> = []
private var hasErrors: Bool {
failedRefundResult.isEmpty == false
}
private var failedRefundResult: [RefundResult] {
results.filter { result in
if case .failure = result.response {
return true
}
return false
}
}
private var errorCount: Int {
failedRefundResult.count
}
var body: some View {
List {
if hasErrors {
RowButtonView("Réessayer tous les remboursements échoués", role: .destructive) {
// Implement retry logic for failed refunds
await _retryFailedRefund()
}
}
let sorted = results.sorted(by: \.team.weight)
ForEach(sorted, id: \.team.id) { result in
LabeledContent {
if processingRetry.contains(result.team.id) {
ProgressView()
} else {
Button {
Task {
await _retryResult(result: result)
}
} label: {
Label("refaire", systemImage: "arrow.2.circlepath.circle").labelStyle(.iconOnly)
}
.buttonStyle(.borderedProminent)
}
} label: {
Text(result.team.teamLabel(twoLines: true))
switch result.response {
case .success(let response):
Text(response.message)
.foregroundColor(response.success ? .green : .logoRed)
case .failure(let error):
Text(error.localizedDescription)
.foregroundColor(.logoRed)
}
}
}
}
.navigationTitle("Résultats des remboursements")
.toolbarBackground(.visible, for: .bottomBar, .navigationBar)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
if hasErrors {
Label("\(errorCount) erreur\(errorCount.pluralSuffix)", systemImage: "exclamationmark.triangle")
.foregroundColor(.red)
} else {
Label("Remboursements effectués", systemImage: "checkmark.circle.fill")
.foregroundColor(.green)
}
}
}
}
private func _retryResult(result: RefundResult) async {
processingRetry.insert(result.team.id)
do {
let response = try await RefundService.processRefund(teamRegistrationId: result.team.id)
results.removeAll(where: { $0.team.id == result.team.id })
results.append(RefundResult(team: result.team, response: .success(response)))
} catch {
results.removeAll(where: { $0.team.id == result.team.id })
results.append(RefundResult(team: result.team, response: .failure(error)))
}
processingRetry.remove(result.team.id)
}
private func _retryFailedRefund() async {
let failed = failedRefundResult
await failed.concurrentForEach { result in
results.removeAll(where: { $0.team.id == result.team.id })
do {
let response = try await RefundService.processRefund(teamRegistrationId: result.team.id)
if let players = response.players {
tournament.tournamentStore?.playerRegistrations.addOrUpdate(contentOfs: players)
}
results.append(RefundResult(team: result.team, response: .success(response)))
} catch {
results.append(RefundResult(team: result.team, response: .failure(error)))
}
}
}
}

@ -13,10 +13,12 @@ struct TournamentStatusView: View {
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel @Environment(NavigationViewModel.self) private var navigation: NavigationViewModel
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
@Bindable var tournament: Tournament @Bindable var tournament: Tournament
@State private var refundResults: [RefundResult] = []
var eventDismiss: Bool = false var eventDismiss: Bool = false
var body: some View { var body: some View {
Form { List {
#if DEBUG #if DEBUG
RowButtonView("debug: Un-delete le tournoi") { RowButtonView("debug: Un-delete le tournoi") {
tournament.endDate = nil tournament.endDate = nil
@ -44,13 +46,28 @@ struct TournamentStatusView: View {
let paidOnlineTeams = tournament.paidOnlineTeams() let paidOnlineTeams = tournament.paidOnlineTeams()
let onlineTeams = tournament.onlineTeams()
if onlineTeams.isEmpty == false {
Section {
LabeledContent {
Text(onlineTeams.count.formatted())
} label: {
Text("Équipes inscrites ligne")
}
Text("Vous avez des équipes inscrites en ligne, en effacant ou supprimant votre tournoi, Padel Club saura prévenir les équipes inscrites en ligne automatiquement.")
.foregroundStyle(.logoRed)
}
}
Section { Section {
RowButtonView("Supprimer le tournoi", role: .destructive) { RowButtonView("Supprimer le tournoi", role: .destructive) {
if tournament.payment == nil { if tournament.payment == nil {
let event = tournament.eventObject() let event = tournament.eventObject()
let isLastTournament = event?.tournaments.count == 1 let isLastTournament = event?.tournaments.count == 1
if tournament.onlineTeams().isEmpty == false { if onlineTeams.isEmpty == false {
tournament.isDeleted = true tournament.isDeleted = true
dataStore.tournaments.addOrUpdate(instance: tournament) dataStore.tournaments.addOrUpdate(instance: tournament)
} else { } else {
@ -88,7 +105,6 @@ struct TournamentStatusView: View {
} }
.disabled(paidOnlineTeams.isEmpty == false) .disabled(paidOnlineTeams.isEmpty == false)
if tournament.hasEnded() == false && tournament.isCanceled == false {
Section { Section {
@Bindable var bindableTournament: Tournament = tournament @Bindable var bindableTournament: Tournament = tournament
@ -142,6 +158,28 @@ struct TournamentStatusView: View {
Text("Si vous annulez ce tournoi vous pouvez toujours gérer les remboursements au cas par cas dans la vue gestion des inscriptions du tournoi.") Text("Si vous annulez ce tournoi vous pouvez toujours gérer les remboursements au cas par cas dans la vue gestion des inscriptions du tournoi.")
} }
if refundResults.isEmpty == false {
NavigationLink {
RefundResultsView(results: $refundResults, tournament: tournament)
} label: {
LabeledContent {
Text("Statut des remboursements")
} label: {
let errorCount = refundResults.filter { result in
if case .failure = result.response { return true }
return false
}.count
if errorCount > 0 {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(.logoRed)
} else {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
}
}
}
}
RowButtonView("Annuler le tournoi", role: .destructive) { RowButtonView("Annuler le tournoi", role: .destructive) {
if paidOnlineTeams.isEmpty == false { if paidOnlineTeams.isEmpty == false {
@ -149,10 +187,10 @@ struct TournamentStatusView: View {
if tournament.enableOnlinePaymentRefund { if tournament.enableOnlinePaymentRefund {
if let refundDateLimit = tournament.refundDateLimit { if let refundDateLimit = tournament.refundDateLimit {
if refundDateLimit.isEarlierThan(Date()) == false { if refundDateLimit.isEarlierThan(Date()) == false {
tournament.refundTeams() await _refundTeams()
} }
} else { } else {
tournament.refundTeams() await _refundTeams()
} }
} }
} }
@ -161,10 +199,10 @@ struct TournamentStatusView: View {
_save() _save()
dismiss() dismiss()
} }
.disabled(tournament.hasEnded() || tournament.isCanceled)
} footer: { } footer: {
Text(.init("Si votre tournoi n'a pas pu aboutir à cause de la météo ou autre, vous pouvez l'annuler et il ne sera pas comptabilisé dans vos achats. Toutes les données du tournoi seront conservées. Le tournoi reste visible sur [Padel Club](\(URLs.main.rawValue))")) Text(.init("Si votre tournoi n'a pas pu aboutir à cause de la météo ou autre, vous pouvez l'annuler et il ne sera pas comptabilisé dans vos achats. Toutes les données du tournoi seront conservées. Le tournoi reste visible sur [Padel Club](\(URLs.main.rawValue))"))
} }
}
// Section { // Section {
// Toggle(isOn: $tournament.isPrivate) { // Toggle(isOn: $tournament.isPrivate) {
@ -190,11 +228,26 @@ struct TournamentStatusView: View {
} }
} }
private func _refundTeams() async {
let paidOnlineTeams = tournament.paidOnlineTeams()
var results: [RefundResult] = []
await paidOnlineTeams.concurrentForEach { team in
do {
let response = try await RefundService.processRefund(teamRegistrationId: team.id)
if let players = response.players {
tournament.tournamentStore?.playerRegistrations.addOrUpdate(contentOfs: players)
}
results.append(RefundResult(team: team, response: .success(response)))
} catch {
results.append(RefundResult(team: team, response: .failure(error)))
}
}
self.refundResults = results
}
private func _save() { private func _save() {
dataStore.tournaments.addOrUpdate(instance: tournament) dataStore.tournaments.addOrUpdate(instance: tournament)
} }
} }
//#Preview {
// TournamentStatusView()
//}

@ -377,7 +377,8 @@ struct RegistrationSetupView: View {
if let fee = dataStore.user.registrationPaymentMode.localizedRegistrationPaymentFee() { if let fee = dataStore.user.registrationPaymentMode.localizedRegistrationPaymentFee() {
let entryFee = tournament.entryFee ?? 20 let entryFee = tournament.entryFee ?? 20
Text("Cette fonction entraîne un coût supplémentaire, en effet Padel Club touchera une commission de \(fee) par paiement en ligne. Soit \(dataStore.user.registrationPaymentMode.sample(entryFee: entryFee)) centimes pour une inscription de \(entryFee)€ par exemple.").foregroundStyle(.logoRed).bold() let sample = dataStore.user.registrationPaymentMode.sample(entryFee: entryFee)
Text("Cette fonction entraîne un coût supplémentaire, en effet Padel Club touchera une commission de \(fee) par paiement en ligne. Soit \(sample) centimes pour une inscription de \(entryFee)€ par exemple.").foregroundStyle(.logoRed).bold()
} }
Toggle(isOn: $onlinePaymentIsMandatory) { Toggle(isOn: $onlinePaymentIsMandatory) {
@ -474,7 +475,7 @@ struct RegistrationSetupView: View {
Task { Task {
isValidating = true isValidating = true
do { do {
let response = try await _validateStripeAccountID(accId) let response = try await StripeValidationService.validateStripeAccountID(accId)
stripeAccountId = accId stripeAccountId = accId
stripeAccountIdIsInvalid = response.valid == false stripeAccountIdIsInvalid = response.valid == false
enableOnlinePayment = response.valid enableOnlinePayment = response.valid
@ -486,64 +487,6 @@ struct RegistrationSetupView: View {
} }
} }
private func _validateStripeAccountID(_ accountID: String) async throws -> ValidationResponse {
let apiPath = "\(URLs.activationHost.rawValue)/utils/validate-stripe-account/"
let url = URL(string: apiPath)!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body = ["account_id": accountID]
request.httpBody = try JSONEncoder().encode(body)
do {
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
throw ValidationError.invalidResponse
}
switch httpResponse.statusCode {
case 200...299:
let decodedResponse = try JSONDecoder().decode(ValidationResponse.self, from: data)
return decodedResponse
case 400:
// Handle bad request
let errorResponse = try JSONDecoder().decode(ValidationResponse.self, from: data)
return errorResponse
case 403:
// Handle permission error
let errorResponse = try JSONDecoder().decode(ValidationResponse.self, from: data)
return errorResponse
default:
throw ValidationError.invalidResponse
}
} catch let error as ValidationError {
throw error
} catch {
throw ValidationError.networkError(error)
}
}
struct ValidationResponse: Codable {
let valid: Bool
let account: AccountDetails?
let error: String?
}
struct AccountDetails: Codable {
let id: String
enum CodingKeys: String, CodingKey {
case id
}
}
enum ValidationError: Error {
case invalidResponse
case networkError(Error)
case invalidData
}
private func _hasChanged() { private func _hasChanged() {
hasChanges = true hasChanges = true
} }

@ -11,9 +11,36 @@ import LeStorage
struct TournamentInitView: View { struct TournamentInitView: View {
@EnvironmentObject var dataStore: DataStore @EnvironmentObject var dataStore: DataStore
var tournament: Tournament var tournament: Tournament
@State private var cashierStatus: Tournament.TournamentStatus?
@ViewBuilder @ViewBuilder
var body: some View { var body: some View {
if tournament.paidOnlineTeams().isEmpty == false {
Section {
NavigationLink(value: Screen.cashier) {
let tournamentStatus = cashierStatus
LabeledContent {
if let tournamentStatus {
Text(tournamentStatus.completion)
} else {
ProgressView()
}
} label: {
Text(tournament.isFree() ? "Présence" : "Encaissement")
if let tournamentStatus {
Text(tournamentStatus.label).lineLimit(1)
} else {
Text(" ")
}
}
}
.task(priority: .background) {
cashierStatus = await tournament.cashierStatus()
}
}
}
Section { Section {
if let event = tournament.eventObject() { if let event = tournament.eventObject() {

Loading…
Cancel
Save