lib.rs (26064B)
1 #![forbid(unsafe_code)] 2 3 use serde::{Deserialize, Serialize}; 4 use std::{fmt, str::FromStr}; 5 use uuid::Uuid; 6 7 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] 8 #[serde(rename_all = "snake_case")] 9 pub enum SettingsSection { 10 #[default] 11 Account, 12 Farm, 13 Settings, 14 About, 15 } 16 17 impl SettingsSection { 18 pub const fn storage_key(self) -> &'static str { 19 match self { 20 Self::Account => "settings.account", 21 Self::Farm => "settings.farm", 22 Self::Settings => "settings.settings", 23 Self::About => "settings.about", 24 } 25 } 26 } 27 28 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 29 #[serde(rename_all = "snake_case")] 30 pub enum SettingsPreference { 31 AllowRelayConnections, 32 UseMediaServers, 33 UseNip05, 34 LaunchAtLogin, 35 } 36 37 impl SettingsPreference { 38 pub const fn storage_key(self) -> &'static str { 39 match self { 40 Self::AllowRelayConnections => "allow_relay_connections", 41 Self::UseMediaServers => "use_media_servers", 42 Self::UseNip05 => "use_nip05", 43 Self::LaunchAtLogin => "launch_at_login", 44 } 45 } 46 } 47 48 macro_rules! typed_id { 49 ($name:ident) => { 50 #[derive( 51 Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, 52 )] 53 #[serde(transparent)] 54 pub struct $name(Uuid); 55 56 impl $name { 57 pub fn new() -> Self { 58 Self(Uuid::now_v7()) 59 } 60 61 pub fn as_uuid(self) -> Uuid { 62 self.0 63 } 64 } 65 66 impl From<Uuid> for $name { 67 fn from(value: Uuid) -> Self { 68 Self(value) 69 } 70 } 71 72 impl From<$name> for Uuid { 73 fn from(value: $name) -> Self { 74 value.0 75 } 76 } 77 78 impl fmt::Display for $name { 79 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 80 self.0.fmt(formatter) 81 } 82 } 83 84 impl FromStr for $name { 85 type Err = uuid::Error; 86 87 fn from_str(value: &str) -> Result<Self, Self::Err> { 88 Uuid::parse_str(value).map(Self) 89 } 90 } 91 92 impl TryFrom<&str> for $name { 93 type Error = uuid::Error; 94 95 fn try_from(value: &str) -> Result<Self, Self::Error> { 96 value.parse() 97 } 98 } 99 }; 100 } 101 102 typed_id!(FarmId); 103 104 typed_id!(PickupLocationId); 105 106 typed_id!(BlackoutPeriodId); 107 108 typed_id!(ProductId); 109 110 typed_id!(OrderId); 111 112 typed_id!(FulfillmentWindowId); 113 114 typed_id!(PackDayExportInstanceId); 115 116 typed_id!(ActivityEventId); 117 118 typed_id!(ReminderId); 119 120 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 121 #[serde(rename_all = "snake_case")] 122 pub enum AccountCustody { 123 LocalManaged, 124 BrowserSigner, 125 RemoteSigner, 126 } 127 128 impl AccountCustody { 129 pub const fn storage_key(self) -> &'static str { 130 match self { 131 Self::LocalManaged => "local_managed", 132 Self::BrowserSigner => "browser_signer", 133 Self::RemoteSigner => "remote_signer", 134 } 135 } 136 } 137 138 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 139 #[serde(rename_all = "snake_case")] 140 pub enum FarmReadiness { 141 Incomplete, 142 Ready, 143 } 144 145 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 146 pub struct FarmProfileRecord { 147 pub farm_id: FarmId, 148 pub display_name: String, 149 pub timezone: String, 150 pub currency_code: String, 151 } 152 153 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 154 pub struct FarmOperatingRulesRecord { 155 pub farm_id: FarmId, 156 pub promise_lead_hours: u16, 157 pub substitution_policy: String, 158 } 159 160 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 161 pub struct PickupLocationRecord { 162 pub pickup_location_id: PickupLocationId, 163 pub farm_id: FarmId, 164 pub label: String, 165 pub address_line: String, 166 pub directions: Option<String>, 167 pub is_default: bool, 168 } 169 170 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 171 pub struct FulfillmentWindowRecord { 172 pub fulfillment_window_id: FulfillmentWindowId, 173 pub farm_id: FarmId, 174 pub pickup_location_id: PickupLocationId, 175 pub label: String, 176 pub starts_at: String, 177 pub ends_at: String, 178 pub order_cutoff_at: String, 179 } 180 181 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 182 pub struct BlackoutPeriodRecord { 183 pub blackout_period_id: BlackoutPeriodId, 184 pub farm_id: FarmId, 185 pub label: String, 186 pub starts_at: String, 187 pub ends_at: String, 188 } 189 190 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 191 #[serde(rename_all = "snake_case")] 192 pub enum FarmReadinessBlocker { 193 MissingProfileBasics, 194 MissingPickupLocation, 195 MissingFulfillmentWindow, 196 MissingOperatingRules, 197 } 198 199 impl FarmReadinessBlocker { 200 pub const fn storage_key(self) -> &'static str { 201 match self { 202 Self::MissingProfileBasics => "missing_profile_basics", 203 Self::MissingPickupLocation => "missing_pickup_location", 204 Self::MissingFulfillmentWindow => "missing_fulfillment_window", 205 Self::MissingOperatingRules => "missing_operating_rules", 206 } 207 } 208 } 209 210 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 211 #[serde(rename_all = "snake_case")] 212 pub enum FarmTimingConflictKind { 213 FulfillmentWindowEndsBeforeStart, 214 FulfillmentWindowCutoffAfterStart, 215 BlackoutPeriodEndsBeforeStart, 216 BlackoutOverlapsFulfillmentWindow, 217 } 218 219 impl FarmTimingConflictKind { 220 pub const fn storage_key(self) -> &'static str { 221 match self { 222 Self::FulfillmentWindowEndsBeforeStart => "fulfillment_window_ends_before_start", 223 Self::FulfillmentWindowCutoffAfterStart => "fulfillment_window_cutoff_after_start", 224 Self::BlackoutPeriodEndsBeforeStart => "blackout_period_ends_before_start", 225 Self::BlackoutOverlapsFulfillmentWindow => "blackout_overlaps_fulfillment_window", 226 } 227 } 228 } 229 230 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 231 pub struct FarmTimingConflict { 232 pub kind: FarmTimingConflictKind, 233 pub fulfillment_window_id: Option<FulfillmentWindowId>, 234 pub blackout_period_id: Option<BlackoutPeriodId>, 235 } 236 237 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 238 pub struct FarmRulesReadiness { 239 pub blockers: Vec<FarmReadinessBlocker>, 240 pub timing_conflicts: Vec<FarmTimingConflict>, 241 } 242 243 impl FarmRulesReadiness { 244 pub fn ready() -> Self { 245 Self { 246 blockers: Vec::new(), 247 timing_conflicts: Vec::new(), 248 } 249 } 250 251 pub fn missing_v1_basics() -> Self { 252 Self { 253 blockers: vec![ 254 FarmReadinessBlocker::MissingProfileBasics, 255 FarmReadinessBlocker::MissingPickupLocation, 256 FarmReadinessBlocker::MissingFulfillmentWindow, 257 FarmReadinessBlocker::MissingOperatingRules, 258 ], 259 timing_conflicts: Vec::new(), 260 } 261 } 262 263 pub fn is_ready(&self) -> bool { 264 self.blockers.is_empty() && self.timing_conflicts.is_empty() 265 } 266 } 267 268 impl Default for FarmRulesReadiness { 269 fn default() -> Self { 270 Self::ready() 271 } 272 } 273 274 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] 275 #[serde(rename_all = "snake_case")] 276 pub enum ProductStatus { 277 #[default] 278 Draft, 279 Published, 280 Paused, 281 Archived, 282 } 283 284 impl ProductStatus { 285 pub const fn storage_key(self) -> &'static str { 286 match self { 287 Self::Draft => "draft", 288 Self::Published => "published", 289 Self::Paused => "paused", 290 Self::Archived => "archived", 291 } 292 } 293 294 pub const fn is_live(self) -> bool { 295 matches!(self, Self::Published) 296 } 297 } 298 299 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 300 #[serde(rename_all = "snake_case")] 301 pub enum ProductPublishBlocker { 302 AddProductName, 303 ChooseCategory, 304 ChooseUnit, 305 SetPrice, 306 SetStock, 307 AttachAvailability, 308 CompleteFarmProfile, 309 AddPickupLocation, 310 AddOperatingRules, 311 AddFulfillmentWindow, 312 ResolveAvailabilityConflicts, 313 } 314 315 impl ProductPublishBlocker { 316 pub const fn storage_key(self) -> &'static str { 317 match self { 318 Self::AddProductName => "add_product_name", 319 Self::ChooseCategory => "choose_category", 320 Self::ChooseUnit => "choose_unit", 321 Self::SetPrice => "set_price", 322 Self::SetStock => "set_stock", 323 Self::AttachAvailability => "attach_availability", 324 Self::CompleteFarmProfile => "complete_farm_profile", 325 Self::AddPickupLocation => "add_pickup_location", 326 Self::AddOperatingRules => "add_operating_rules", 327 Self::AddFulfillmentWindow => "add_fulfillment_window", 328 Self::ResolveAvailabilityConflicts => "resolve_availability_conflicts", 329 } 330 } 331 } 332 333 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 334 #[serde(rename_all = "snake_case")] 335 pub enum OrderStatus { 336 NeedsAction, 337 Scheduled, 338 Packed, 339 Completed, 340 Declined, 341 NeedsReview, 342 } 343 344 impl OrderStatus { 345 pub const fn storage_key(self) -> &'static str { 346 match self { 347 Self::NeedsAction => "needs_action", 348 Self::Scheduled => "scheduled", 349 Self::Packed => "packed", 350 Self::Completed => "completed", 351 Self::Declined => "declined", 352 Self::NeedsReview => "needs_review", 353 } 354 } 355 } 356 357 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 358 #[serde(rename_all = "snake_case")] 359 pub enum BuyerOrderStatus { 360 Placed, 361 Scheduled, 362 Ready, 363 Completed, 364 Declined, 365 NeedsReview, 366 } 367 368 impl BuyerOrderStatus { 369 pub const fn storage_key(self) -> &'static str { 370 match self { 371 Self::Placed => "placed", 372 Self::Scheduled => "scheduled", 373 Self::Ready => "ready", 374 Self::Completed => "completed", 375 Self::Declined => "declined", 376 Self::NeedsReview => "needs_review", 377 } 378 } 379 } 380 381 impl From<OrderStatus> for BuyerOrderStatus { 382 fn from(value: OrderStatus) -> Self { 383 match value { 384 OrderStatus::NeedsAction => Self::Placed, 385 OrderStatus::Scheduled => Self::Scheduled, 386 OrderStatus::Packed => Self::Ready, 387 OrderStatus::Completed => Self::Completed, 388 OrderStatus::Declined => Self::Declined, 389 OrderStatus::NeedsReview => Self::NeedsReview, 390 } 391 } 392 } 393 394 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 395 #[serde(rename_all = "snake_case")] 396 pub enum PackDayExportArtifactKind { 397 PackSheet, 398 PickupRoster, 399 CustomerLabels, 400 } 401 402 impl PackDayExportArtifactKind { 403 pub const fn all_v1() -> [Self; 3] { 404 [Self::PackSheet, Self::PickupRoster, Self::CustomerLabels] 405 } 406 407 pub const fn storage_key(self) -> &'static str { 408 match self { 409 Self::PackSheet => "pack_sheet", 410 Self::PickupRoster => "pickup_roster", 411 Self::CustomerLabels => "customer_labels", 412 } 413 } 414 415 pub const fn file_name(self) -> &'static str { 416 match self { 417 Self::PackSheet => "pack_sheet.txt", 418 Self::PickupRoster => "pickup_roster.txt", 419 Self::CustomerLabels => "customer_labels.txt", 420 } 421 } 422 } 423 424 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 425 #[serde(rename_all = "snake_case")] 426 pub enum PackDayPrintKind { 427 PrintPackSheet, 428 PrintPickupRoster, 429 PrintCustomerLabels, 430 } 431 432 impl PackDayPrintKind { 433 pub const fn all_v1() -> [Self; 3] { 434 [ 435 Self::PrintPackSheet, 436 Self::PrintPickupRoster, 437 Self::PrintCustomerLabels, 438 ] 439 } 440 441 pub const fn storage_key(self) -> &'static str { 442 match self { 443 Self::PrintPackSheet => "print_pack_sheet", 444 Self::PrintPickupRoster => "print_pickup_roster", 445 Self::PrintCustomerLabels => "print_customer_labels", 446 } 447 } 448 449 pub const fn artifact_kind(self) -> PackDayExportArtifactKind { 450 match self { 451 Self::PrintPackSheet => PackDayExportArtifactKind::PackSheet, 452 Self::PrintPickupRoster => PackDayExportArtifactKind::PickupRoster, 453 Self::PrintCustomerLabels => PackDayExportArtifactKind::CustomerLabels, 454 } 455 } 456 457 pub const fn label_stock(self) -> Option<PackDayPrintLabelStock> { 458 match self { 459 Self::PrintPackSheet | Self::PrintPickupRoster => None, 460 Self::PrintCustomerLabels => Some(PackDayPrintLabelStock::Avery5160Letter30Up), 461 } 462 } 463 } 464 465 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 466 #[serde(rename_all = "snake_case")] 467 pub enum PackDayPrintLabelStock { 468 Avery5160Letter30Up, 469 } 470 471 impl PackDayPrintLabelStock { 472 pub const fn all_v1() -> [Self; 1] { 473 [Self::Avery5160Letter30Up] 474 } 475 476 pub const fn storage_key(self) -> &'static str { 477 match self { 478 Self::Avery5160Letter30Up => "avery_5160_letter_30_up", 479 } 480 } 481 } 482 483 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 484 #[serde(rename_all = "snake_case")] 485 pub enum PackDayPrintFailureKind { 486 CustomerLabelsAvery5160Overflow, 487 } 488 489 impl PackDayPrintFailureKind { 490 pub const fn storage_key(self) -> &'static str { 491 match self { 492 Self::CustomerLabelsAvery5160Overflow => "customer_labels_avery_5160_overflow", 493 } 494 } 495 } 496 497 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 498 pub struct PackDayBatchPrintArtifact { 499 pub print_kind: PackDayPrintKind, 500 pub artifact_kind: PackDayExportArtifactKind, 501 pub label_stock: Option<PackDayPrintLabelStock>, 502 } 503 504 impl PackDayBatchPrintArtifact { 505 pub const fn all_v1() -> [Self; 3] { 506 [ 507 Self::from_print_kind(PackDayPrintKind::PrintPackSheet), 508 Self::from_print_kind(PackDayPrintKind::PrintPickupRoster), 509 Self::from_print_kind(PackDayPrintKind::PrintCustomerLabels), 510 ] 511 } 512 513 pub const fn from_print_kind(print_kind: PackDayPrintKind) -> Self { 514 Self { 515 print_kind, 516 artifact_kind: print_kind.artifact_kind(), 517 label_stock: print_kind.label_stock(), 518 } 519 } 520 } 521 522 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 523 #[serde(rename_all = "snake_case")] 524 pub enum PackDayBatchPrintFailureKind { 525 Preflight, 526 QueueLaunch, 527 QueueExit, 528 CustomerLabelsAvery5160Overflow, 529 } 530 531 impl PackDayBatchPrintFailureKind { 532 pub const fn storage_key(self) -> &'static str { 533 match self { 534 Self::Preflight => "preflight", 535 Self::QueueLaunch => "queue_launch", 536 Self::QueueExit => "queue_exit", 537 Self::CustomerLabelsAvery5160Overflow => "customer_labels_avery_5160_overflow", 538 } 539 } 540 } 541 542 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] 543 #[serde(rename_all = "snake_case")] 544 pub enum PackDayBatchPrintStatus { 545 #[default] 546 Idle, 547 Running, 548 Succeeded, 549 Failed, 550 } 551 552 impl PackDayBatchPrintStatus { 553 pub const fn storage_key(self) -> &'static str { 554 match self { 555 Self::Idle => "idle", 556 Self::Running => "running", 557 Self::Succeeded => "succeeded", 558 Self::Failed => "failed", 559 } 560 } 561 } 562 563 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] 564 #[serde(rename_all = "snake_case")] 565 pub enum PackDayPrintStatus { 566 #[default] 567 Idle, 568 Running, 569 Succeeded, 570 Failed, 571 } 572 573 impl PackDayPrintStatus { 574 pub const fn storage_key(self) -> &'static str { 575 match self { 576 Self::Idle => "idle", 577 Self::Running => "running", 578 Self::Succeeded => "succeeded", 579 Self::Failed => "failed", 580 } 581 } 582 } 583 584 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 585 #[serde(rename_all = "snake_case")] 586 pub enum PackDayHostHandoffKind { 587 RevealBundle, 588 OpenPackSheet, 589 OpenPickupRoster, 590 OpenCustomerLabels, 591 } 592 593 impl PackDayHostHandoffKind { 594 pub const fn all_v1() -> [Self; 4] { 595 [ 596 Self::RevealBundle, 597 Self::OpenPackSheet, 598 Self::OpenPickupRoster, 599 Self::OpenCustomerLabels, 600 ] 601 } 602 603 pub const fn storage_key(self) -> &'static str { 604 match self { 605 Self::RevealBundle => "reveal_bundle", 606 Self::OpenPackSheet => "open_pack_sheet", 607 Self::OpenPickupRoster => "open_pickup_roster", 608 Self::OpenCustomerLabels => "open_customer_labels", 609 } 610 } 611 612 pub const fn artifact_kind(self) -> Option<PackDayExportArtifactKind> { 613 match self { 614 Self::RevealBundle => None, 615 Self::OpenPackSheet => Some(PackDayExportArtifactKind::PackSheet), 616 Self::OpenPickupRoster => Some(PackDayExportArtifactKind::PickupRoster), 617 Self::OpenCustomerLabels => Some(PackDayExportArtifactKind::CustomerLabels), 618 } 619 } 620 } 621 622 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] 623 #[serde(rename_all = "snake_case")] 624 pub enum PackDayExportStatus { 625 #[default] 626 Idle, 627 Running, 628 Succeeded, 629 Failed, 630 } 631 632 impl PackDayExportStatus { 633 pub const fn storage_key(self) -> &'static str { 634 match self { 635 Self::Idle => "idle", 636 Self::Running => "running", 637 Self::Succeeded => "succeeded", 638 Self::Failed => "failed", 639 } 640 } 641 } 642 643 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] 644 #[serde(rename_all = "snake_case")] 645 pub enum PackDayHostHandoffStatus { 646 #[default] 647 Idle, 648 Running, 649 Succeeded, 650 Failed, 651 } 652 653 impl PackDayHostHandoffStatus { 654 pub const fn storage_key(self) -> &'static str { 655 match self { 656 Self::Idle => "idle", 657 Self::Running => "running", 658 Self::Succeeded => "succeeded", 659 Self::Failed => "failed", 660 } 661 } 662 } 663 664 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 665 #[serde(rename_all = "snake_case")] 666 pub enum PackDayOutputOrderState { 667 NeedsAction, 668 Scheduled, 669 Packed, 670 } 671 672 impl PackDayOutputOrderState { 673 pub const fn all_v1() -> [Self; 3] { 674 [Self::NeedsAction, Self::Scheduled, Self::Packed] 675 } 676 677 pub const fn storage_key(self) -> &'static str { 678 match self { 679 Self::NeedsAction => "needs_action", 680 Self::Scheduled => "scheduled", 681 Self::Packed => "packed", 682 } 683 } 684 685 pub const fn from_order_status(status: OrderStatus) -> Option<Self> { 686 match status { 687 OrderStatus::NeedsAction => Some(Self::NeedsAction), 688 OrderStatus::Scheduled => Some(Self::Scheduled), 689 OrderStatus::Packed => Some(Self::Packed), 690 OrderStatus::Completed | OrderStatus::Declined | OrderStatus::NeedsReview => None, 691 } 692 } 693 } 694 695 impl From<PackDayOutputOrderState> for OrderStatus { 696 fn from(value: PackDayOutputOrderState) -> Self { 697 match value { 698 PackDayOutputOrderState::NeedsAction => Self::NeedsAction, 699 PackDayOutputOrderState::Scheduled => Self::Scheduled, 700 PackDayOutputOrderState::Packed => Self::Packed, 701 } 702 } 703 } 704 705 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 706 pub struct PackDayOutputQuantity { 707 pub value: u32, 708 pub unit_label: String, 709 } 710 711 impl PackDayOutputQuantity { 712 pub fn new(value: u32, unit_label: impl Into<String>) -> Self { 713 Self { 714 value, 715 unit_label: unit_label.into(), 716 } 717 } 718 } 719 720 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 721 pub struct PackDayOutputWindow { 722 pub fulfillment_window_id: FulfillmentWindowId, 723 pub farm_id: FarmId, 724 pub farm_display_name: String, 725 pub pickup_location_label: Option<String>, 726 pub starts_at: String, 727 pub ends_at: String, 728 } 729 730 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 731 pub struct PackDayOutputProductTotal { 732 pub title: String, 733 pub quantity: PackDayOutputQuantity, 734 } 735 736 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 737 pub struct PackDayOutputPackListEntry { 738 pub order_id: OrderId, 739 pub order_number: String, 740 pub customer_display_name: String, 741 pub order_state: PackDayOutputOrderState, 742 pub title: String, 743 pub quantity: PackDayOutputQuantity, 744 } 745 746 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 747 pub struct PackDayOutputCustomerOrder { 748 pub order_id: OrderId, 749 pub order_number: String, 750 pub customer_display_name: String, 751 pub order_state: PackDayOutputOrderState, 752 } 753 754 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 755 pub struct PackDayOutputSource { 756 pub fulfillment_window: PackDayOutputWindow, 757 pub totals_by_product: Vec<PackDayOutputProductTotal>, 758 pub pack_list: Vec<PackDayOutputPackListEntry>, 759 pub pickup_roster: Vec<PackDayOutputCustomerOrder>, 760 } 761 762 impl PackDayOutputSource { 763 pub fn is_empty(&self) -> bool { 764 self.totals_by_product.is_empty() 765 && self.pack_list.is_empty() 766 && self.pickup_roster.is_empty() 767 } 768 } 769 770 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 771 pub struct PackDayExportArtifact { 772 pub kind: PackDayExportArtifactKind, 773 pub relative_path: String, 774 } 775 776 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 777 pub struct PackDayExportBundle { 778 pub fulfillment_window_id: FulfillmentWindowId, 779 pub export_instance_id: PackDayExportInstanceId, 780 pub generated_at_utc: String, 781 pub bundle_directory: String, 782 pub artifacts: Vec<PackDayExportArtifact>, 783 } 784 785 impl PackDayExportBundle { 786 pub fn artifact_count(&self) -> usize { 787 self.artifacts.len() 788 } 789 790 pub fn includes_artifact(&self, kind: PackDayExportArtifactKind) -> bool { 791 self.artifacts.iter().any(|artifact| artifact.kind == kind) 792 } 793 } 794 795 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] 796 #[serde(rename_all = "snake_case")] 797 pub enum FarmOrderMethod { 798 Pickup, 799 Delivery, 800 Shipping, 801 } 802 803 impl FarmOrderMethod { 804 pub const fn storage_key(self) -> &'static str { 805 match self { 806 Self::Pickup => "pickup", 807 Self::Delivery => "delivery", 808 Self::Shipping => "shipping", 809 } 810 } 811 } 812 813 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 814 #[serde(rename_all = "snake_case")] 815 pub enum ReminderSurface { 816 Today, 817 Orders, 818 PackDay, 819 } 820 821 impl ReminderSurface { 822 pub const fn storage_key(self) -> &'static str { 823 match self { 824 Self::Today => "today", 825 Self::Orders => "orders", 826 Self::PackDay => "pack_day", 827 } 828 } 829 } 830 831 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 832 #[serde(rename_all = "snake_case")] 833 pub enum ReminderKind { 834 FulfillmentWindow, 835 OrderAction, 836 SyncImpact, 837 } 838 839 impl ReminderKind { 840 pub const fn storage_key(self) -> &'static str { 841 match self { 842 Self::FulfillmentWindow => "fulfillment_window", 843 Self::OrderAction => "order_action", 844 Self::SyncImpact => "sync_impact", 845 } 846 } 847 } 848 849 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 850 #[serde(rename_all = "snake_case")] 851 pub enum ReminderUrgency { 852 Upcoming, 853 DueSoon, 854 Overdue, 855 Blocking, 856 } 857 858 impl ReminderUrgency { 859 pub const fn storage_key(self) -> &'static str { 860 match self { 861 Self::Upcoming => "upcoming", 862 Self::DueSoon => "due_soon", 863 Self::Overdue => "overdue", 864 Self::Blocking => "blocking", 865 } 866 } 867 } 868 869 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 870 #[serde(rename_all = "snake_case")] 871 pub enum ReminderDeliveryState { 872 Scheduled, 873 Presented, 874 Acknowledged, 875 Resolved, 876 } 877 878 impl ReminderDeliveryState { 879 pub const fn storage_key(self) -> &'static str { 880 match self { 881 Self::Scheduled => "scheduled", 882 Self::Presented => "presented", 883 Self::Acknowledged => "acknowledged", 884 Self::Resolved => "resolved", 885 } 886 } 887 } 888 889 #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] 890 #[serde(rename_all = "snake_case")] 891 pub enum RepeatDemandEligibility { 892 Eligible, 893 Partial, 894 Unavailable, 895 } 896 897 impl RepeatDemandEligibility { 898 pub const fn storage_key(self) -> &'static str { 899 match self { 900 Self::Eligible => "eligible", 901 Self::Partial => "partial", 902 Self::Unavailable => "unavailable", 903 } 904 } 905 } 906 907 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 908 pub enum AppActivityKind { 909 HomeOpened, 910 SettingsOpened { 911 section: SettingsSection, 912 }, 913 SettingsSectionSelected { 914 section: SettingsSection, 915 }, 916 SettingsPreferenceUpdated { 917 preference: SettingsPreference, 918 enabled: bool, 919 }, 920 } 921 922 impl AppActivityKind { 923 pub const fn storage_key(&self) -> &'static str { 924 match self { 925 Self::HomeOpened => "home_opened", 926 Self::SettingsOpened { .. } => "settings_opened", 927 Self::SettingsSectionSelected { .. } => "settings_section_selected", 928 Self::SettingsPreferenceUpdated { .. } => "settings_preference_updated", 929 } 930 } 931 } 932 933 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] 934 pub struct AppActivityEvent { 935 pub activity_event_id: ActivityEventId, 936 pub recorded_at: String, 937 pub kind: AppActivityKind, 938 } 939 940 #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] 941 pub struct AppActivityContext { 942 pub recent_events: Vec<AppActivityEvent>, 943 } 944 945 impl AppActivityContext { 946 pub fn from_recent_events(recent_events: Vec<AppActivityEvent>) -> Self { 947 Self { recent_events } 948 } 949 }