Imports
The Imports module brings files into records that are not content items (content types use Orchard Core's content transfer). The feature reads a CSV file, maps its columns to a target's fields, has the target check every row, imports, and offers the failed rows back as CSV. Each module offers its own targets.
| Projects | CrestApps.Almohaseb.Imports (module), CrestApps.Almohaseb.Imports.Core (contracts, CSV reader, mapping, templates) |
| Feature | CrestApps.Almohaseb.Imports (Imports); depends on the foundation; enabled by both business recipes |
| Collection | Imports (templates) |
Contracts
All in CrestApps.Almohaseb.Imports (Imports.Core):
IImportTarget:Name(unique, in the URL),DisplayName,Description,Permission,Fields(ImportField:Key,Name,Required,Hint,Aliasesfor guessing),Options(ImportOption: check boxes for the whole import),ValidateAsync(rows, settings)andImportAsync(rows, settings, user)returningImportOutcome(Imported,Errors). A module registers its targets as scopedIImportTargetservices in a startup with[RequireFeatures(ImportsConstants.Feature)].ImportRow(Number, the 1-based row of the file;Valuesby field key;Get(key)trimmed ornull),ImportRowError(Row,Message, localized by the target),ImportSettings(DateFormat,Options;Has(key)).ImportMapping(HasHeader,Columnsby field key, 0-based,DateFormat) andImportTemplate(Target,Name,Mapping), kept byIImportTemplateStore(ListAsync(target),GetAsync,SaveAsync(target, name, mapping, user)replacing a template of the same name,DeleteAsync) withImportTemplateIndex(Target, Name).
Pure helpers:
CsvReader.Parse(text): RFC 4180 (quoted fields, doubled quotes, line breaks inside quotes), the separator detected from the first line (comma, semicolon or tab), a byte order mark dropped, empty lines skipped. Banking reads statements with it.ImportValues.TryParseAmount(1,234.56,$-12.00,(12.00),12.00-),TryParseOptionalAmount(empty is 0),TryParseDate(text, format)(the format, or US and ISO dates; a time after the date ignored).ImportMapper.Guess(header, fields, hasHeader)(a column whose name, ignoring case and punctuation, is the field's key, name or an alias; without a header the columns in order),Map(rows, mapping)(short rows get empty values),Unmapped(mapping, fields)(required fields without a column),FailedRows(rows, mapping, errors)(the header and the failed rows with aProblemcolumn; values quoted when needed; a value starting with=,+,-or@that is not a number gets a leading apostrophe so a spreadsheet does not run it).
Admin
Tools > Import files (almohasebImports, permission ImportAlmohasebFiles). The flow is stateless: the file's text travels in the form.
| Route (under the admin prefix) | Route name | |
|---|---|---|
Almohaseb/Import | AlmohasebImports | the targets the user has the permission of |
Almohaseb/Import/{target} | AlmohasebImportTarget | GET the upload form; POST file or content, hasHeader, templateId → the mapping |
Almohaseb/Import/{target}/Check | AlmohasebImportCheck | POST Content, HasHeader, DateFormat, Columns[key] (-1 for none), Options, TemplateName, SaveTemplate → the problems of each row |
Almohaseb/Import/{target}/Run | AlmohasebImportRun | POST the same → the outcome and the failed rows (a data: CSV link) |
Files are limited to 2 MB (ImportsConstants.MaxLength). Every action checks ImportAlmohasebFiles and the target's permission.
| Permission | Key | |
|---|---|---|
| Import files | ImportAlmohasebFiles | Administrator |
Targets of the Ledger
Registered by the Ledger's ImportsStartup:
JournalEntryImportTarget(journal-entries,ManageAlmohasebJournal): fieldsEntry,Date,Account,Debit,Credit,Amount,Description,Memo; optionpost. Rows group byEntry, else by the date and description as written. An account is found by number, by name, or by the number before a separator ("1000 · Cash"). A negative debit is a credit. An entry is left out when a row cannot be read, its dates differ, it does not balance or it has one line; the error is on every row of the entry, so the failed rows can be imported again. Entries are posted (IJournalService.PostAsync) with the option, else saved as drafts; the journal's own errors (closed period, inactive account) come back on the entry's rows.OpeningBalanceImportTarget(opening-balances,CloseAlmohasebPeriods): fieldsDate,Account,Debit,Credit,Amount(balance). One date, each account once, balanced, at least one balance; all or nothing throughIOpeningBalanceService.SaveAsync, which replaces the saved opening balances.