1use serde::{Deserialize, Serialize};
33
34use crate::models::AccountSubType;
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46pub enum AdcType {
47 Asset,
49 Liability,
51 Equity,
53 Revenue,
55 Expense,
57}
58
59impl AdcType {
60 pub fn code(&self) -> &'static str {
62 match self {
63 Self::Asset => "A",
64 Self::Liability => "L",
65 Self::Equity => "E",
66 Self::Revenue => "R",
67 Self::Expense => "X",
68 }
69 }
70
71 pub fn name(&self) -> &'static str {
73 match self {
74 Self::Asset => "Assets",
75 Self::Liability => "Liabilities",
76 Self::Equity => "Equity",
77 Self::Revenue => "Revenue",
78 Self::Expense => "Expenses",
79 }
80 }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
91#[serde(rename_all = "snake_case")]
92pub enum AdcClass {
93 AssetCash,
96 AssetReceivables,
98 AssetInventory,
100 AssetPrepaid,
102 AssetInvestments,
104 AssetPpe,
106 AssetIntangible,
108 AssetOtherLongTerm,
110 AssetSuspense,
112
113 LiabilityPayables,
116 LiabilityAccrued,
118 LiabilityShortTermDebt,
120 LiabilityTax,
122 LiabilityLongTermDebt,
124 LiabilityOther,
126
127 EquityContributed,
130 EquityRetained,
132 EquityOci,
134 EquityTreasury,
136
137 RevenueOperating,
140 RevenueOther,
142
143 ExpenseCogs,
146 ExpenseSga,
148 ExpenseDepAmort,
150 ExpenseInterest,
152 ExpenseTax,
154 ExpenseOther,
156}
157
158impl AdcClass {
159 pub fn code(&self) -> &'static str {
161 match self {
162 Self::AssetCash => "A.A",
163 Self::AssetReceivables => "A.B",
164 Self::AssetInventory => "A.C",
165 Self::AssetPrepaid => "A.D",
166 Self::AssetInvestments => "A.E",
167 Self::AssetPpe => "A.F",
168 Self::AssetIntangible => "A.G",
169 Self::AssetOtherLongTerm => "A.H",
170 Self::AssetSuspense => "A.X",
171 Self::LiabilityPayables => "L.A",
172 Self::LiabilityAccrued => "L.B",
173 Self::LiabilityShortTermDebt => "L.C",
174 Self::LiabilityTax => "L.D",
175 Self::LiabilityLongTermDebt => "L.E",
176 Self::LiabilityOther => "L.F",
177 Self::EquityContributed => "E.A",
178 Self::EquityRetained => "E.B",
179 Self::EquityOci => "E.C",
180 Self::EquityTreasury => "E.D",
181 Self::RevenueOperating => "R.A",
182 Self::RevenueOther => "R.B",
183 Self::ExpenseCogs => "X.A",
184 Self::ExpenseSga => "X.B",
185 Self::ExpenseDepAmort => "X.D",
186 Self::ExpenseInterest => "X.E",
187 Self::ExpenseTax => "X.F",
188 Self::ExpenseOther => "X.G",
189 }
190 }
191
192 pub fn name(&self) -> &'static str {
194 match self {
195 Self::AssetCash => "Cash & Cash Equivalents",
196 Self::AssetReceivables => "Trade Receivables",
197 Self::AssetInventory => "Inventory",
198 Self::AssetPrepaid => "Prepaid Expenses & Other Current Assets",
199 Self::AssetInvestments => "Long-term Investments",
200 Self::AssetPpe => "Property, Plant & Equipment",
201 Self::AssetIntangible => "Intangible Assets",
202 Self::AssetOtherLongTerm => "Other Long-term Assets",
203 Self::AssetSuspense => "Suspense & Clearing (Asset side)",
204 Self::LiabilityPayables => "Trade Payables",
205 Self::LiabilityAccrued => "Accrued Liabilities",
206 Self::LiabilityShortTermDebt => "Short-term Debt",
207 Self::LiabilityTax => "Tax Liabilities",
208 Self::LiabilityLongTermDebt => "Long-term Debt",
209 Self::LiabilityOther => "Other Long-term Liabilities",
210 Self::EquityContributed => "Contributed Capital",
211 Self::EquityRetained => "Retained Earnings",
212 Self::EquityOci => "Other Comprehensive Income",
213 Self::EquityTreasury => "Treasury Stock",
214 Self::RevenueOperating => "Operating Revenue",
215 Self::RevenueOther => "Other Income",
216 Self::ExpenseCogs => "Cost of Goods Sold",
217 Self::ExpenseSga => "Selling, General & Administrative",
218 Self::ExpenseDepAmort => "Depreciation & Amortisation",
219 Self::ExpenseInterest => "Interest Expense",
220 Self::ExpenseTax => "Tax Expense",
221 Self::ExpenseOther => "Other Expenses",
222 }
223 }
224
225 pub fn adc_type(&self) -> AdcType {
227 match self {
228 Self::AssetCash
229 | Self::AssetReceivables
230 | Self::AssetInventory
231 | Self::AssetPrepaid
232 | Self::AssetInvestments
233 | Self::AssetPpe
234 | Self::AssetIntangible
235 | Self::AssetOtherLongTerm
236 | Self::AssetSuspense => AdcType::Asset,
237 Self::LiabilityPayables
238 | Self::LiabilityAccrued
239 | Self::LiabilityShortTermDebt
240 | Self::LiabilityTax
241 | Self::LiabilityLongTermDebt
242 | Self::LiabilityOther => AdcType::Liability,
243 Self::EquityContributed
244 | Self::EquityRetained
245 | Self::EquityOci
246 | Self::EquityTreasury => AdcType::Equity,
247 Self::RevenueOperating | Self::RevenueOther => AdcType::Revenue,
248 Self::ExpenseCogs
249 | Self::ExpenseSga
250 | Self::ExpenseDepAmort
251 | Self::ExpenseInterest
252 | Self::ExpenseTax
253 | Self::ExpenseOther => AdcType::Expense,
254 }
255 }
256}
257
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
268#[serde(rename_all = "snake_case")]
269pub enum AdcSubClass {
270 AssetCashOperating,
273 AssetCashBankClearing,
275 AssetTradeAr,
277 AssetOtherReceivables,
279 AssetInventoryGeneral,
281 AssetPrepaidExpenses,
283 AssetInvestmentsLongTerm,
285 AssetFixedAssets,
287 AssetAccumulatedDepreciation,
289 AssetIntangibleAssets,
291 AssetOtherAssets,
293 AssetSuspenseClearing,
295 AssetIntercompanyClearing,
297
298 LiabilityTradeAp,
301 LiabilityAccruedExpenses,
303 LiabilityDeferredRevenue,
305 LiabilityGoodsReceivedClearing,
307 LiabilityShortTermDebt,
309 LiabilityTaxLiabilities,
311 LiabilityLongTermDebt,
313 LiabilityPensionLiabilities,
315 LiabilityOtherLiabilities,
317
318 EquityCommonStock,
321 EquityAdditionalPaidIn,
323 EquityRetainedEarnings,
325 EquityNetIncome,
327 EquityOtherComprehensiveIncome,
329 EquityTreasuryStock,
331
332 RevenueProduct,
335 RevenueService,
337 RevenueInterestIncome,
339 RevenueDividendIncome,
341 RevenueGainOnSale,
343 RevenueOtherIncome,
345
346 ExpenseCostOfGoodsSold,
349 ExpenseOperatingExpenses,
351 ExpenseSellingExpenses,
353 ExpenseAdministrativeExpenses,
355 ExpenseDepreciationExpense,
357 ExpenseAmortisationExpense,
359 ExpenseInterestExpense,
361 ExpenseTaxExpense,
363 ExpenseForeignExchangeLoss,
365 ExpenseLossOnSale,
367 ExpenseOtherExpenses,
369}
370
371impl AdcSubClass {
372 pub fn code(&self) -> &'static str {
374 match self {
375 Self::AssetCashOperating => "A.A.A",
376 Self::AssetCashBankClearing => "A.A.B",
377 Self::AssetTradeAr => "A.B.A",
378 Self::AssetOtherReceivables => "A.B.B",
379 Self::AssetInventoryGeneral => "A.C.A",
380 Self::AssetPrepaidExpenses => "A.D.A",
381 Self::AssetInvestmentsLongTerm => "A.E.A",
382 Self::AssetFixedAssets => "A.F.A",
383 Self::AssetAccumulatedDepreciation => "A.F.B",
384 Self::AssetIntangibleAssets => "A.G.A",
385 Self::AssetOtherAssets => "A.H.A",
386 Self::AssetSuspenseClearing => "A.X.A",
387 Self::AssetIntercompanyClearing => "A.X.B",
388 Self::LiabilityTradeAp => "L.A.A",
389 Self::LiabilityAccruedExpenses => "L.B.A",
390 Self::LiabilityDeferredRevenue => "L.B.B",
391 Self::LiabilityGoodsReceivedClearing => "L.B.C",
392 Self::LiabilityShortTermDebt => "L.C.A",
393 Self::LiabilityTaxLiabilities => "L.D.A",
394 Self::LiabilityLongTermDebt => "L.E.A",
395 Self::LiabilityPensionLiabilities => "L.F.A",
396 Self::LiabilityOtherLiabilities => "L.F.B",
397 Self::EquityCommonStock => "E.A.A",
398 Self::EquityAdditionalPaidIn => "E.A.B",
399 Self::EquityRetainedEarnings => "E.B.A",
400 Self::EquityNetIncome => "E.B.B",
401 Self::EquityOtherComprehensiveIncome => "E.C.A",
402 Self::EquityTreasuryStock => "E.D.A",
403 Self::RevenueProduct => "R.A.A",
404 Self::RevenueService => "R.A.B",
405 Self::RevenueInterestIncome => "R.B.A",
406 Self::RevenueDividendIncome => "R.B.B",
407 Self::RevenueGainOnSale => "R.B.C",
408 Self::RevenueOtherIncome => "R.B.D",
409 Self::ExpenseCostOfGoodsSold => "X.A.A",
410 Self::ExpenseOperatingExpenses => "X.B.A",
411 Self::ExpenseSellingExpenses => "X.B.B",
412 Self::ExpenseAdministrativeExpenses => "X.B.C",
413 Self::ExpenseDepreciationExpense => "X.D.A",
414 Self::ExpenseAmortisationExpense => "X.D.B",
415 Self::ExpenseInterestExpense => "X.E.A",
416 Self::ExpenseTaxExpense => "X.F.A",
417 Self::ExpenseForeignExchangeLoss => "X.G.A",
418 Self::ExpenseLossOnSale => "X.G.B",
419 Self::ExpenseOtherExpenses => "X.G.C",
420 }
421 }
422
423 pub fn name(&self) -> &'static str {
425 match self {
426 Self::AssetCashOperating => "Operating Cash",
427 Self::AssetCashBankClearing => "Bank Clearing",
428 Self::AssetTradeAr => "Trade Accounts Receivable",
429 Self::AssetOtherReceivables => "Other Receivables",
430 Self::AssetInventoryGeneral => "Inventory",
431 Self::AssetPrepaidExpenses => "Prepaid Expenses",
432 Self::AssetInvestmentsLongTerm => "Long-term Investments",
433 Self::AssetFixedAssets => "Fixed Assets",
434 Self::AssetAccumulatedDepreciation => "Accumulated Depreciation",
435 Self::AssetIntangibleAssets => "Intangible Assets",
436 Self::AssetOtherAssets => "Other Assets",
437 Self::AssetSuspenseClearing => "Suspense Clearing",
438 Self::AssetIntercompanyClearing => "Intercompany Clearing",
439 Self::LiabilityTradeAp => "Trade Accounts Payable",
440 Self::LiabilityAccruedExpenses => "Accrued Expenses",
441 Self::LiabilityDeferredRevenue => "Deferred Revenue",
442 Self::LiabilityGoodsReceivedClearing => "GR/IR Clearing",
443 Self::LiabilityShortTermDebt => "Short-term Debt",
444 Self::LiabilityTaxLiabilities => "Tax Liabilities",
445 Self::LiabilityLongTermDebt => "Long-term Debt",
446 Self::LiabilityPensionLiabilities => "Pension Liabilities",
447 Self::LiabilityOtherLiabilities => "Other Liabilities",
448 Self::EquityCommonStock => "Common Stock",
449 Self::EquityAdditionalPaidIn => "Additional Paid-In Capital",
450 Self::EquityRetainedEarnings => "Retained Earnings",
451 Self::EquityNetIncome => "Net Income",
452 Self::EquityOtherComprehensiveIncome => "Other Comprehensive Income",
453 Self::EquityTreasuryStock => "Treasury Stock",
454 Self::RevenueProduct => "Product Revenue",
455 Self::RevenueService => "Service Revenue",
456 Self::RevenueInterestIncome => "Interest Income",
457 Self::RevenueDividendIncome => "Dividend Income",
458 Self::RevenueGainOnSale => "Gain on Sale of Assets",
459 Self::RevenueOtherIncome => "Other Income",
460 Self::ExpenseCostOfGoodsSold => "Cost of Goods Sold",
461 Self::ExpenseOperatingExpenses => "Operating Expenses",
462 Self::ExpenseSellingExpenses => "Selling Expenses",
463 Self::ExpenseAdministrativeExpenses => "Administrative Expenses",
464 Self::ExpenseDepreciationExpense => "Depreciation Expense",
465 Self::ExpenseAmortisationExpense => "Amortisation Expense",
466 Self::ExpenseInterestExpense => "Interest Expense",
467 Self::ExpenseTaxExpense => "Tax Expense",
468 Self::ExpenseForeignExchangeLoss => "Foreign-Exchange Loss",
469 Self::ExpenseLossOnSale => "Loss on Sale of Assets",
470 Self::ExpenseOtherExpenses => "Other Expenses",
471 }
472 }
473
474 pub fn adc_class(&self) -> AdcClass {
476 match self {
477 Self::AssetCashOperating | Self::AssetCashBankClearing => AdcClass::AssetCash,
478 Self::AssetTradeAr | Self::AssetOtherReceivables => AdcClass::AssetReceivables,
479 Self::AssetInventoryGeneral => AdcClass::AssetInventory,
480 Self::AssetPrepaidExpenses => AdcClass::AssetPrepaid,
481 Self::AssetInvestmentsLongTerm => AdcClass::AssetInvestments,
482 Self::AssetFixedAssets | Self::AssetAccumulatedDepreciation => AdcClass::AssetPpe,
483 Self::AssetIntangibleAssets => AdcClass::AssetIntangible,
484 Self::AssetOtherAssets => AdcClass::AssetOtherLongTerm,
485 Self::AssetSuspenseClearing | Self::AssetIntercompanyClearing => {
486 AdcClass::AssetSuspense
487 }
488 Self::LiabilityTradeAp => AdcClass::LiabilityPayables,
489 Self::LiabilityAccruedExpenses
490 | Self::LiabilityDeferredRevenue
491 | Self::LiabilityGoodsReceivedClearing => AdcClass::LiabilityAccrued,
492 Self::LiabilityShortTermDebt => AdcClass::LiabilityShortTermDebt,
493 Self::LiabilityTaxLiabilities => AdcClass::LiabilityTax,
494 Self::LiabilityLongTermDebt => AdcClass::LiabilityLongTermDebt,
495 Self::LiabilityPensionLiabilities | Self::LiabilityOtherLiabilities => {
496 AdcClass::LiabilityOther
497 }
498 Self::EquityCommonStock | Self::EquityAdditionalPaidIn => AdcClass::EquityContributed,
499 Self::EquityRetainedEarnings | Self::EquityNetIncome => AdcClass::EquityRetained,
500 Self::EquityOtherComprehensiveIncome => AdcClass::EquityOci,
501 Self::EquityTreasuryStock => AdcClass::EquityTreasury,
502 Self::RevenueProduct | Self::RevenueService => AdcClass::RevenueOperating,
503 Self::RevenueInterestIncome
504 | Self::RevenueDividendIncome
505 | Self::RevenueGainOnSale
506 | Self::RevenueOtherIncome => AdcClass::RevenueOther,
507 Self::ExpenseCostOfGoodsSold => AdcClass::ExpenseCogs,
508 Self::ExpenseOperatingExpenses
509 | Self::ExpenseSellingExpenses
510 | Self::ExpenseAdministrativeExpenses => AdcClass::ExpenseSga,
511 Self::ExpenseDepreciationExpense | Self::ExpenseAmortisationExpense => {
512 AdcClass::ExpenseDepAmort
513 }
514 Self::ExpenseInterestExpense => AdcClass::ExpenseInterest,
515 Self::ExpenseTaxExpense => AdcClass::ExpenseTax,
516 Self::ExpenseForeignExchangeLoss
517 | Self::ExpenseLossOnSale
518 | Self::ExpenseOtherExpenses => AdcClass::ExpenseOther,
519 }
520 }
521}
522
523pub fn from_account_sub_type(sub_type: AccountSubType) -> AdcSubClass {
536 use AccountSubType as S;
537 match sub_type {
538 S::Cash => AdcSubClass::AssetCashOperating,
539 S::AccountsReceivable => AdcSubClass::AssetTradeAr,
540 S::OtherReceivables => AdcSubClass::AssetOtherReceivables,
541 S::Inventory => AdcSubClass::AssetInventoryGeneral,
542 S::PrepaidExpenses => AdcSubClass::AssetPrepaidExpenses,
543 S::FixedAssets => AdcSubClass::AssetFixedAssets,
544 S::AccumulatedDepreciation => AdcSubClass::AssetAccumulatedDepreciation,
545 S::Investments => AdcSubClass::AssetInvestmentsLongTerm,
546 S::IntangibleAssets => AdcSubClass::AssetIntangibleAssets,
547 S::OtherAssets => AdcSubClass::AssetOtherAssets,
548 S::AccountsPayable => AdcSubClass::LiabilityTradeAp,
549 S::AccruedLiabilities => AdcSubClass::LiabilityAccruedExpenses,
550 S::ShortTermDebt => AdcSubClass::LiabilityShortTermDebt,
551 S::LongTermDebt => AdcSubClass::LiabilityLongTermDebt,
552 S::DeferredRevenue => AdcSubClass::LiabilityDeferredRevenue,
553 S::TaxLiabilities => AdcSubClass::LiabilityTaxLiabilities,
554 S::PensionLiabilities => AdcSubClass::LiabilityPensionLiabilities,
555 S::OtherLiabilities => AdcSubClass::LiabilityOtherLiabilities,
556 S::CommonStock => AdcSubClass::EquityCommonStock,
557 S::RetainedEarnings => AdcSubClass::EquityRetainedEarnings,
558 S::AdditionalPaidInCapital => AdcSubClass::EquityAdditionalPaidIn,
559 S::TreasuryStock => AdcSubClass::EquityTreasuryStock,
560 S::OtherComprehensiveIncome => AdcSubClass::EquityOtherComprehensiveIncome,
561 S::NetIncome => AdcSubClass::EquityNetIncome,
562 S::ProductRevenue => AdcSubClass::RevenueProduct,
563 S::ServiceRevenue => AdcSubClass::RevenueService,
564 S::InterestIncome => AdcSubClass::RevenueInterestIncome,
565 S::DividendIncome => AdcSubClass::RevenueDividendIncome,
566 S::GainOnSale => AdcSubClass::RevenueGainOnSale,
567 S::OtherIncome => AdcSubClass::RevenueOtherIncome,
568 S::CostOfGoodsSold => AdcSubClass::ExpenseCostOfGoodsSold,
569 S::OperatingExpenses => AdcSubClass::ExpenseOperatingExpenses,
570 S::SellingExpenses => AdcSubClass::ExpenseSellingExpenses,
571 S::AdministrativeExpenses => AdcSubClass::ExpenseAdministrativeExpenses,
572 S::DepreciationExpense => AdcSubClass::ExpenseDepreciationExpense,
573 S::AmortizationExpense => AdcSubClass::ExpenseAmortisationExpense,
574 S::InterestExpense => AdcSubClass::ExpenseInterestExpense,
575 S::TaxExpense => AdcSubClass::ExpenseTaxExpense,
576 S::ForeignExchangeLoss => AdcSubClass::ExpenseForeignExchangeLoss,
577 S::LossOnSale => AdcSubClass::ExpenseLossOnSale,
578 S::OtherExpenses => AdcSubClass::ExpenseOtherExpenses,
579 S::SuspenseClearing => AdcSubClass::AssetSuspenseClearing,
580 S::GoodsReceivedClearing => AdcSubClass::LiabilityGoodsReceivedClearing,
581 S::BankClearing => AdcSubClass::AssetCashBankClearing,
582 S::IntercompanyClearing => AdcSubClass::AssetIntercompanyClearing,
583 }
584}
585
586#[cfg(test)]
591mod tests {
592 use super::*;
593 use crate::models::AccountSubType;
594
595 #[test]
600 fn every_account_sub_type_maps_to_valid_iso_codes() {
601 for &sub in &[
602 AccountSubType::Cash,
603 AccountSubType::AccountsReceivable,
604 AccountSubType::OtherReceivables,
605 AccountSubType::Inventory,
606 AccountSubType::PrepaidExpenses,
607 AccountSubType::FixedAssets,
608 AccountSubType::AccumulatedDepreciation,
609 AccountSubType::Investments,
610 AccountSubType::IntangibleAssets,
611 AccountSubType::OtherAssets,
612 AccountSubType::AccountsPayable,
613 AccountSubType::AccruedLiabilities,
614 AccountSubType::ShortTermDebt,
615 AccountSubType::LongTermDebt,
616 AccountSubType::DeferredRevenue,
617 AccountSubType::TaxLiabilities,
618 AccountSubType::PensionLiabilities,
619 AccountSubType::OtherLiabilities,
620 AccountSubType::CommonStock,
621 AccountSubType::RetainedEarnings,
622 AccountSubType::AdditionalPaidInCapital,
623 AccountSubType::TreasuryStock,
624 AccountSubType::OtherComprehensiveIncome,
625 AccountSubType::NetIncome,
626 AccountSubType::ProductRevenue,
627 AccountSubType::ServiceRevenue,
628 AccountSubType::InterestIncome,
629 AccountSubType::DividendIncome,
630 AccountSubType::GainOnSale,
631 AccountSubType::OtherIncome,
632 AccountSubType::CostOfGoodsSold,
633 AccountSubType::OperatingExpenses,
634 AccountSubType::SellingExpenses,
635 AccountSubType::AdministrativeExpenses,
636 AccountSubType::DepreciationExpense,
637 AccountSubType::AmortizationExpense,
638 AccountSubType::InterestExpense,
639 AccountSubType::TaxExpense,
640 AccountSubType::ForeignExchangeLoss,
641 AccountSubType::LossOnSale,
642 AccountSubType::OtherExpenses,
643 AccountSubType::SuspenseClearing,
644 AccountSubType::GoodsReceivedClearing,
645 AccountSubType::BankClearing,
646 AccountSubType::IntercompanyClearing,
647 ] {
648 let sub_class = from_account_sub_type(sub);
649 let class = sub_class.adc_class();
650 let ty = class.adc_type();
651
652 let sub_code = sub_class.code();
655 let class_code = class.code();
656 let type_code = ty.code();
657 assert_eq!(
658 sub_code.len(),
659 5,
660 "sub-class code should be 5 chars: {sub_code}"
661 );
662 assert!(
663 sub_code.starts_with(class_code),
664 "sub-class code {sub_code} should start with class {class_code}"
665 );
666 assert!(
667 class_code.starts_with(type_code),
668 "class code {class_code} should start with type {type_code}"
669 );
670 assert!(
671 !sub_class.name().is_empty(),
672 "sub-class name should not be empty for {sub:?}"
673 );
674 }
675 }
676
677 #[test]
678 fn isocode_examples_are_correct() {
679 assert_eq!(AdcType::Asset.code(), "A");
680 assert_eq!(AdcClass::AssetReceivables.code(), "A.B");
681 assert_eq!(AdcSubClass::AssetTradeAr.code(), "A.B.A");
682 assert_eq!(
683 from_account_sub_type(AccountSubType::AccountsReceivable).code(),
684 "A.B.A"
685 );
686 assert_eq!(
687 from_account_sub_type(AccountSubType::CostOfGoodsSold).code(),
688 "X.A.A"
689 );
690 assert_eq!(
691 from_account_sub_type(AccountSubType::CommonStock).code(),
692 "E.A.A"
693 );
694 }
695
696 #[test]
697 fn parent_relationships_are_consistent() {
698 for sub_class in [
700 AdcSubClass::AssetTradeAr,
701 AdcSubClass::LiabilityTradeAp,
702 AdcSubClass::EquityRetainedEarnings,
703 AdcSubClass::RevenueProduct,
704 AdcSubClass::ExpenseCostOfGoodsSold,
705 ] {
706 let class = sub_class.adc_class();
707 let ty = class.adc_type();
708 assert!(sub_class.code().starts_with(class.code()));
710 assert!(class.code().starts_with(ty.code()));
711 }
712 }
713}