1use crate::application::dto::ChargeDistributionResponseDto;
2use crate::application::ports::{
3 ChargeDistributionRepository, ExpenseRepository, UnitOwnerRepository,
4};
5use crate::domain::entities::{ApprovalStatus, ChargeDistribution};
6use rust_decimal::Decimal;
7use std::sync::Arc;
8use uuid::Uuid;
9
10pub struct ChargeDistributionUseCases {
11 distribution_repository: Arc<dyn ChargeDistributionRepository>,
12 expense_repository: Arc<dyn ExpenseRepository>,
13 unit_owner_repository: Arc<dyn UnitOwnerRepository>,
14}
15
16impl ChargeDistributionUseCases {
17 pub fn new(
18 distribution_repository: Arc<dyn ChargeDistributionRepository>,
19 expense_repository: Arc<dyn ExpenseRepository>,
20 unit_owner_repository: Arc<dyn UnitOwnerRepository>,
21 ) -> Self {
22 Self {
23 distribution_repository,
24 expense_repository,
25 unit_owner_repository,
26 }
27 }
28
29 pub async fn calculate_and_save_distribution(
31 &self,
32 expense_id: Uuid,
33 ) -> Result<Vec<ChargeDistributionResponseDto>, String> {
34 let expense = self
36 .expense_repository
37 .find_by_id(expense_id)
38 .await?
39 .ok_or_else(|| "Expense/Invoice not found".to_string())?;
40
41 if expense.approval_status != ApprovalStatus::Approved {
43 return Err(format!(
44 "Cannot calculate distribution for non-approved invoice (status: {:?})",
45 expense.approval_status
46 ));
47 }
48
49 let total_amount = expense.amount_incl_vat.unwrap_or(expense.amount);
51
52 let unit_ownerships = self
54 .unit_owner_repository
55 .find_active_by_building(expense.building_id)
56 .await?;
57
58 if unit_ownerships.is_empty() {
59 return Err("No active unit-owner relationships found for this building".to_string());
60 }
61
62 let distributions =
64 ChargeDistribution::calculate_distributions(expense_id, total_amount, unit_ownerships)?;
65
66 let saved_distributions = self
68 .distribution_repository
69 .create_bulk(&distributions)
70 .await?;
71
72 Ok(saved_distributions
74 .iter()
75 .map(|d| self.to_response_dto(d))
76 .collect())
77 }
78
79 pub async fn get_distribution_by_expense(
81 &self,
82 expense_id: Uuid,
83 ) -> Result<Vec<ChargeDistributionResponseDto>, String> {
84 let distributions = self
85 .distribution_repository
86 .find_by_expense(expense_id)
87 .await?;
88 Ok(distributions
89 .iter()
90 .map(|d| self.to_response_dto(d))
91 .collect())
92 }
93
94 pub async fn get_distributions_by_owner(
96 &self,
97 owner_id: Uuid,
98 ) -> Result<Vec<ChargeDistributionResponseDto>, String> {
99 let distributions = self.distribution_repository.find_by_owner(owner_id).await?;
100 Ok(distributions
101 .iter()
102 .map(|d| self.to_response_dto(d))
103 .collect())
104 }
105
106 pub async fn get_total_due_by_owner(&self, owner_id: Uuid) -> Result<Decimal, String> {
108 self.distribution_repository
109 .get_total_due_by_owner(owner_id)
110 .await
111 }
112
113 pub async fn delete_distribution_by_expense(&self, expense_id: Uuid) -> Result<(), String> {
115 self.distribution_repository
116 .delete_by_expense(expense_id)
117 .await
118 }
119
120 fn to_response_dto(&self, distribution: &ChargeDistribution) -> ChargeDistributionResponseDto {
121 ChargeDistributionResponseDto {
122 id: distribution.id.to_string(),
123 expense_id: distribution.expense_id.to_string(),
124 unit_id: distribution.unit_id.to_string(),
125 owner_id: distribution.owner_id.to_string(),
126 quota_percentage: distribution.quota_percentage,
127 amount_due: distribution.amount_due,
128 created_at: distribution.created_at.to_rfc3339(),
129 }
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use crate::application::dto::{ExpenseFilters, PageRequest};
137 use crate::application::ports::{
138 ChargeDistributionRepository, ExpenseRepository, UnitOwnerRepository,
139 };
140 use crate::domain::entities::{
141 ApprovalStatus, ChargeDistribution, Expense, ExpenseCategory, PaymentStatus, UnitOwner,
142 };
143 use async_trait::async_trait;
144 use chrono::Utc;
145 use rust_decimal_macros::dec;
146 use std::collections::HashMap;
147 use std::sync::Mutex;
148
149 struct MockChargeDistributionRepository {
152 distributions: Mutex<HashMap<Uuid, ChargeDistribution>>,
153 }
154
155 impl MockChargeDistributionRepository {
156 fn new() -> Self {
157 Self {
158 distributions: Mutex::new(HashMap::new()),
159 }
160 }
161 }
162
163 #[async_trait]
164 impl ChargeDistributionRepository for MockChargeDistributionRepository {
165 async fn create(
166 &self,
167 distribution: &ChargeDistribution,
168 ) -> Result<ChargeDistribution, String> {
169 let mut distributions = self.distributions.lock().unwrap();
170 distributions.insert(distribution.id, distribution.clone());
171 Ok(distribution.clone())
172 }
173
174 async fn create_bulk(
175 &self,
176 distributions: &[ChargeDistribution],
177 ) -> Result<Vec<ChargeDistribution>, String> {
178 let mut store = self.distributions.lock().unwrap();
179 let mut result = Vec::new();
180 for d in distributions {
181 store.insert(d.id, d.clone());
182 result.push(d.clone());
183 }
184 Ok(result)
185 }
186
187 async fn find_by_id(&self, id: Uuid) -> Result<Option<ChargeDistribution>, String> {
188 let distributions = self.distributions.lock().unwrap();
189 Ok(distributions.get(&id).cloned())
190 }
191
192 async fn find_by_expense(
193 &self,
194 expense_id: Uuid,
195 ) -> Result<Vec<ChargeDistribution>, String> {
196 let distributions = self.distributions.lock().unwrap();
197 Ok(distributions
198 .values()
199 .filter(|d| d.expense_id == expense_id)
200 .cloned()
201 .collect())
202 }
203
204 async fn find_by_unit(&self, unit_id: Uuid) -> Result<Vec<ChargeDistribution>, String> {
205 let distributions = self.distributions.lock().unwrap();
206 Ok(distributions
207 .values()
208 .filter(|d| d.unit_id == unit_id)
209 .cloned()
210 .collect())
211 }
212
213 async fn find_by_owner(&self, owner_id: Uuid) -> Result<Vec<ChargeDistribution>, String> {
214 let distributions = self.distributions.lock().unwrap();
215 Ok(distributions
216 .values()
217 .filter(|d| d.owner_id == owner_id)
218 .cloned()
219 .collect())
220 }
221
222 async fn delete_by_expense(&self, expense_id: Uuid) -> Result<(), String> {
223 let mut distributions = self.distributions.lock().unwrap();
224 distributions.retain(|_, d| d.expense_id != expense_id);
225 Ok(())
226 }
227
228 async fn get_total_due_by_owner(&self, owner_id: Uuid) -> Result<Decimal, String> {
229 let distributions = self.distributions.lock().unwrap();
230 let total = distributions
231 .values()
232 .filter(|d| d.owner_id == owner_id)
233 .map(|d| d.amount_due)
234 .sum();
235 Ok(total)
236 }
237 }
238
239 struct MockExpenseRepository {
242 expenses: Mutex<HashMap<Uuid, Expense>>,
243 }
244
245 impl MockExpenseRepository {
246 fn new() -> Self {
247 Self {
248 expenses: Mutex::new(HashMap::new()),
249 }
250 }
251
252 fn with_expense(expense: Expense) -> Self {
253 let mut map = HashMap::new();
254 map.insert(expense.id, expense);
255 Self {
256 expenses: Mutex::new(map),
257 }
258 }
259 }
260
261 #[async_trait]
262 impl ExpenseRepository for MockExpenseRepository {
263 async fn create(&self, expense: &Expense) -> Result<Expense, String> {
264 let mut expenses = self.expenses.lock().unwrap();
265 expenses.insert(expense.id, expense.clone());
266 Ok(expense.clone())
267 }
268
269 async fn find_by_id(&self, id: Uuid) -> Result<Option<Expense>, String> {
270 let expenses = self.expenses.lock().unwrap();
271 Ok(expenses.get(&id).cloned())
272 }
273
274 async fn find_by_building(&self, building_id: Uuid) -> Result<Vec<Expense>, String> {
275 let expenses = self.expenses.lock().unwrap();
276 Ok(expenses
277 .values()
278 .filter(|e| e.building_id == building_id)
279 .cloned()
280 .collect())
281 }
282
283 async fn find_all_paginated(
284 &self,
285 _page_request: &PageRequest,
286 _filters: &ExpenseFilters,
287 ) -> Result<(Vec<Expense>, i64), String> {
288 let expenses = self.expenses.lock().unwrap();
289 let all: Vec<Expense> = expenses.values().cloned().collect();
290 let count = all.len() as i64;
291 Ok((all, count))
292 }
293
294 async fn update(&self, expense: &Expense) -> Result<Expense, String> {
295 let mut expenses = self.expenses.lock().unwrap();
296 expenses.insert(expense.id, expense.clone());
297 Ok(expense.clone())
298 }
299
300 async fn delete(&self, id: Uuid) -> Result<bool, String> {
301 let mut expenses = self.expenses.lock().unwrap();
302 Ok(expenses.remove(&id).is_some())
303 }
304 }
305
306 type BuildingOwnerships = HashMap<Uuid, Vec<(Uuid, Uuid, Decimal)>>;
310
311 struct MockUnitOwnerRepository {
312 building_ownerships: Mutex<BuildingOwnerships>,
314 }
315
316 impl MockUnitOwnerRepository {
317 fn new() -> Self {
318 Self {
319 building_ownerships: Mutex::new(HashMap::new()),
320 }
321 }
322
323 fn with_building_ownerships(
324 building_id: Uuid,
325 ownerships: Vec<(Uuid, Uuid, Decimal)>,
326 ) -> Self {
327 let mut map = HashMap::new();
328 map.insert(building_id, ownerships);
329 Self {
330 building_ownerships: Mutex::new(map),
331 }
332 }
333 }
334
335 #[async_trait]
336 impl UnitOwnerRepository for MockUnitOwnerRepository {
337 async fn create(&self, _unit_owner: &UnitOwner) -> Result<UnitOwner, String> {
338 unimplemented!("not needed for charge distribution tests")
339 }
340
341 async fn find_by_id(&self, _id: Uuid) -> Result<Option<UnitOwner>, String> {
342 unimplemented!("not needed for charge distribution tests")
343 }
344
345 async fn find_current_owners_by_unit(
346 &self,
347 _unit_id: Uuid,
348 ) -> Result<Vec<UnitOwner>, String> {
349 unimplemented!("not needed for charge distribution tests")
350 }
351
352 async fn find_current_units_by_owner(
353 &self,
354 _owner_id: Uuid,
355 ) -> Result<Vec<UnitOwner>, String> {
356 unimplemented!("not needed for charge distribution tests")
357 }
358
359 async fn find_all_owners_by_unit(&self, _unit_id: Uuid) -> Result<Vec<UnitOwner>, String> {
360 unimplemented!("not needed for charge distribution tests")
361 }
362
363 async fn find_all_units_by_owner(&self, _owner_id: Uuid) -> Result<Vec<UnitOwner>, String> {
364 unimplemented!("not needed for charge distribution tests")
365 }
366
367 async fn update(&self, _unit_owner: &UnitOwner) -> Result<UnitOwner, String> {
368 unimplemented!("not needed for charge distribution tests")
369 }
370
371 async fn delete(&self, _id: Uuid) -> Result<(), String> {
372 unimplemented!("not needed for charge distribution tests")
373 }
374
375 async fn has_active_owners(&self, _unit_id: Uuid) -> Result<bool, String> {
376 unimplemented!("not needed for charge distribution tests")
377 }
378
379 async fn get_total_ownership_percentage(&self, _unit_id: Uuid) -> Result<Decimal, String> {
380 unimplemented!("not needed for charge distribution tests")
381 }
382
383 async fn find_active_by_unit_and_owner(
384 &self,
385 _unit_id: Uuid,
386 _owner_id: Uuid,
387 ) -> Result<Option<UnitOwner>, String> {
388 unimplemented!("not needed for charge distribution tests")
389 }
390
391 async fn find_active_by_building(
392 &self,
393 building_id: Uuid,
394 ) -> Result<Vec<(Uuid, Uuid, Decimal)>, String> {
395 let ownerships = self.building_ownerships.lock().unwrap();
396 Ok(ownerships.get(&building_id).cloned().unwrap_or_default())
397 }
398 }
399
400 fn make_approved_expense(building_id: Uuid, amount_incl_vat: Decimal) -> Expense {
403 let now = Utc::now();
404 let vat_factor = dec!(1.21);
405 let amount_excl_vat = amount_incl_vat / vat_factor;
406 Expense {
407 id: Uuid::new_v4(),
408 organization_id: Uuid::new_v4(),
409 building_id,
410 category: ExpenseCategory::Maintenance,
411 description: "Elevator maintenance".to_string(),
412 amount: amount_incl_vat,
413 amount_excl_vat: Some(amount_excl_vat),
414 vat_rate: Some(dec!(21)),
415 vat_amount: Some(amount_incl_vat - amount_excl_vat),
416 amount_incl_vat: Some(amount_incl_vat),
417 expense_date: now,
418 invoice_date: Some(now),
419 due_date: None,
420 paid_date: None,
421 approval_status: ApprovalStatus::Approved,
422 submitted_at: Some(now),
423 approved_by: Some(Uuid::new_v4()),
424 approved_at: Some(now),
425 rejection_reason: None,
426 payment_status: PaymentStatus::Pending,
427 supplier: Some("Schindler SA".to_string()),
428 invoice_number: Some("INV-001".to_string()),
429 account_code: Some("611002".to_string()),
430 contractor_report_id: None,
431 created_at: now,
432 updated_at: now,
433 }
434 }
435
436 fn make_draft_expense(building_id: Uuid) -> Expense {
437 let now = Utc::now();
438 Expense {
439 id: Uuid::new_v4(),
440 organization_id: Uuid::new_v4(),
441 building_id,
442 category: ExpenseCategory::Maintenance,
443 description: "Draft expense".to_string(),
444 amount: dec!(1000),
445 amount_excl_vat: None,
446 vat_rate: None,
447 vat_amount: None,
448 amount_incl_vat: None,
449 expense_date: now,
450 invoice_date: None,
451 due_date: None,
452 paid_date: None,
453 approval_status: ApprovalStatus::Draft,
454 submitted_at: None,
455 approved_by: None,
456 approved_at: None,
457 rejection_reason: None,
458 payment_status: PaymentStatus::Pending,
459 supplier: None,
460 invoice_number: None,
461 account_code: None,
462 contractor_report_id: None,
463 created_at: now,
464 updated_at: now,
465 }
466 }
467
468 fn make_use_cases(
469 dist_repo: MockChargeDistributionRepository,
470 expense_repo: MockExpenseRepository,
471 unit_owner_repo: MockUnitOwnerRepository,
472 ) -> ChargeDistributionUseCases {
473 ChargeDistributionUseCases::new(
474 Arc::new(dist_repo),
475 Arc::new(expense_repo),
476 Arc::new(unit_owner_repo),
477 )
478 }
479
480 #[tokio::test]
483 async fn test_calculate_and_save_distribution_success() {
484 let building_id = Uuid::new_v4();
485 let unit1_id = Uuid::new_v4();
486 let unit2_id = Uuid::new_v4();
487 let owner1_id = Uuid::new_v4();
488 let owner2_id = Uuid::new_v4();
489
490 let expense = make_approved_expense(building_id, dec!(1000));
491 let expense_id = expense.id;
492
493 let ownerships = vec![
494 (unit1_id, owner1_id, dec!(0.60)), (unit2_id, owner2_id, dec!(0.40)), ];
497
498 let dist_repo = MockChargeDistributionRepository::new();
499 let expense_repo = MockExpenseRepository::with_expense(expense);
500 let unit_owner_repo =
501 MockUnitOwnerRepository::with_building_ownerships(building_id, ownerships);
502
503 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
504
505 let result = uc.calculate_and_save_distribution(expense_id).await;
506 assert!(result.is_ok());
507
508 let distributions = result.unwrap();
509 assert_eq!(distributions.len(), 2);
510
511 let total_amount: Decimal = distributions.iter().map(|d| d.amount_due).sum();
513 assert_eq!(total_amount, dec!(1000));
514
515 assert!(distributions
517 .iter()
518 .all(|d| d.expense_id == expense_id.to_string()));
519 }
520
521 #[tokio::test]
522 async fn test_calculate_and_save_distribution_non_approved_expense() {
523 let building_id = Uuid::new_v4();
524 let expense = make_draft_expense(building_id);
525 let expense_id = expense.id;
526
527 let dist_repo = MockChargeDistributionRepository::new();
528 let expense_repo = MockExpenseRepository::with_expense(expense);
529 let unit_owner_repo = MockUnitOwnerRepository::new();
530
531 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
532
533 let result = uc.calculate_and_save_distribution(expense_id).await;
534 assert!(result.is_err());
535 let err = result.unwrap_err();
536 assert!(err.contains("non-approved invoice"));
537 }
538
539 #[tokio::test]
540 async fn test_calculate_and_save_distribution_expense_not_found() {
541 let dist_repo = MockChargeDistributionRepository::new();
542 let expense_repo = MockExpenseRepository::new(); let unit_owner_repo = MockUnitOwnerRepository::new();
544
545 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
546
547 let result = uc.calculate_and_save_distribution(Uuid::new_v4()).await;
548 assert!(result.is_err());
549 assert_eq!(result.unwrap_err(), "Expense/Invoice not found");
550 }
551
552 #[tokio::test]
553 async fn test_calculate_and_save_distribution_no_active_owners() {
554 let building_id = Uuid::new_v4();
555 let expense = make_approved_expense(building_id, dec!(1000));
556 let expense_id = expense.id;
557
558 let dist_repo = MockChargeDistributionRepository::new();
559 let expense_repo = MockExpenseRepository::with_expense(expense);
560 let unit_owner_repo =
562 MockUnitOwnerRepository::with_building_ownerships(building_id, vec![]);
563
564 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
565
566 let result = uc.calculate_and_save_distribution(expense_id).await;
567 assert!(result.is_err());
568 assert_eq!(
569 result.unwrap_err(),
570 "No active unit-owner relationships found for this building"
571 );
572 }
573
574 #[tokio::test]
575 async fn test_get_distribution_by_expense() {
576 let building_id = Uuid::new_v4();
577 let unit1_id = Uuid::new_v4();
578 let owner1_id = Uuid::new_v4();
579
580 let expense = make_approved_expense(building_id, dec!(500));
581 let expense_id = expense.id;
582
583 let ownerships = vec![(unit1_id, owner1_id, Decimal::ONE)]; let dist_repo = MockChargeDistributionRepository::new();
586 let expense_repo = MockExpenseRepository::with_expense(expense);
587 let unit_owner_repo =
588 MockUnitOwnerRepository::with_building_ownerships(building_id, ownerships);
589
590 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
591
592 uc.calculate_and_save_distribution(expense_id)
594 .await
595 .unwrap();
596
597 let result = uc.get_distribution_by_expense(expense_id).await;
599 assert!(result.is_ok());
600 let distributions = result.unwrap();
601 assert_eq!(distributions.len(), 1);
602 assert_eq!(distributions[0].expense_id, expense_id.to_string());
603 assert_eq!(distributions[0].quota_percentage, Decimal::ONE);
604 assert_eq!(distributions[0].amount_due, dec!(500.00));
605 }
606
607 #[tokio::test]
608 async fn test_get_distribution_by_expense_empty() {
609 let dist_repo = MockChargeDistributionRepository::new();
610 let expense_repo = MockExpenseRepository::new();
611 let unit_owner_repo = MockUnitOwnerRepository::new();
612
613 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
614
615 let result = uc.get_distribution_by_expense(Uuid::new_v4()).await;
616 assert!(result.is_ok());
617 assert!(result.unwrap().is_empty());
618 }
619
620 #[tokio::test]
621 async fn test_get_total_due_by_owner() {
622 let building_id = Uuid::new_v4();
623 let unit1_id = Uuid::new_v4();
624 let unit2_id = Uuid::new_v4();
625 let owner1_id = Uuid::new_v4();
626 let owner2_id = Uuid::new_v4();
627
628 let expense1 = make_approved_expense(building_id, dec!(1000));
630 let expense1_id = expense1.id;
631 let expense2 = make_approved_expense(building_id, dec!(2000));
632 let expense2_id = expense2.id;
633
634 let ownerships = vec![
635 (unit1_id, owner1_id, dec!(0.60)), (unit2_id, owner2_id, dec!(0.40)), ];
638
639 let dist_repo = MockChargeDistributionRepository::new();
640 let mut expense_map = HashMap::new();
641 expense_map.insert(expense1.id, expense1);
642 expense_map.insert(expense2.id, expense2);
643 let expense_repo = MockExpenseRepository {
644 expenses: Mutex::new(expense_map),
645 };
646 let unit_owner_repo =
647 MockUnitOwnerRepository::with_building_ownerships(building_id, ownerships);
648
649 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
650
651 uc.calculate_and_save_distribution(expense1_id)
653 .await
654 .unwrap();
655 uc.calculate_and_save_distribution(expense2_id)
656 .await
657 .unwrap();
658
659 let total = uc.get_total_due_by_owner(owner1_id).await.unwrap();
661 assert_eq!(total, dec!(1800.00));
662
663 let total = uc.get_total_due_by_owner(owner2_id).await.unwrap();
665 assert_eq!(total, dec!(1200.00));
666 }
667
668 #[tokio::test]
669 async fn test_get_total_due_by_owner_no_distributions() {
670 let dist_repo = MockChargeDistributionRepository::new();
671 let expense_repo = MockExpenseRepository::new();
672 let unit_owner_repo = MockUnitOwnerRepository::new();
673
674 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
675
676 let total = uc.get_total_due_by_owner(Uuid::new_v4()).await.unwrap();
677 assert_eq!(total, Decimal::ZERO);
678 }
679
680 #[tokio::test]
681 async fn test_calculate_distribution_uses_amount_incl_vat() {
682 let building_id = Uuid::new_v4();
683 let unit_id = Uuid::new_v4();
684 let owner_id = Uuid::new_v4();
685
686 let now = Utc::now();
688 let expense = Expense {
689 id: Uuid::new_v4(),
690 organization_id: Uuid::new_v4(),
691 building_id,
692 category: ExpenseCategory::Utilities,
693 description: "Electricity".to_string(),
694 amount: dec!(1000),
695 amount_excl_vat: Some(dec!(1000)),
696 vat_rate: Some(dec!(21)),
697 vat_amount: Some(dec!(210)),
698 amount_incl_vat: Some(dec!(1210)),
699 expense_date: now,
700 invoice_date: Some(now),
701 due_date: None,
702 paid_date: None,
703 approval_status: ApprovalStatus::Approved,
704 submitted_at: Some(now),
705 approved_by: Some(Uuid::new_v4()),
706 approved_at: Some(now),
707 rejection_reason: None,
708 payment_status: PaymentStatus::Pending,
709 supplier: None,
710 invoice_number: None,
711 account_code: None,
712 contractor_report_id: None,
713 created_at: now,
714 updated_at: now,
715 };
716 let expense_id = expense.id;
717
718 let ownerships = vec![(unit_id, owner_id, Decimal::ONE)]; let dist_repo = MockChargeDistributionRepository::new();
721 let expense_repo = MockExpenseRepository::with_expense(expense);
722 let unit_owner_repo =
723 MockUnitOwnerRepository::with_building_ownerships(building_id, ownerships);
724
725 let uc = make_use_cases(dist_repo, expense_repo, unit_owner_repo);
726
727 let result = uc
728 .calculate_and_save_distribution(expense_id)
729 .await
730 .unwrap();
731
732 assert_eq!(result.len(), 1);
734 assert_eq!(result[0].amount_due, dec!(1210));
735 }
736}