Skip to main content
Technical ManualLooking for step-by-step instructions? In the User Manual: CustomersVendorsVendor Categories

Contacts

The Contacts module keeps the customers, the vendors and the vendor categories of a business. They are Orchard Core content types, so the content list, search, bulk actions, per-type permissions and content deployment come with them. The address and phone numbers are CrestApps content fields.

ProjectsCrestApps.Almohaseb.Contacts (module), CrestApps.Almohaseb.Contacts.Core (parts, indexes, rules, directory)
FeatureCrestApps.Almohaseb.Contacts (Customers & vendors), enabled by both business recipes
LegacyBOOK-07 Customers, BOOK-14 Vendors, BOOK-15 Vendor Categories

Features and dependencies​

CrestApps.Almohaseb.Contacts depends on:

  • CrestApps.Almohaseb (the foundation) and CrestApps.Almohaseb.Ledger (Accounting), for the vendor's default account and the protected tax ID;
  • OrchardCore.Contents;
  • CrestApps.OrchardCore.ContentFields (PhoneField; it brings in CrestApps Resources, Phone Numbers, OrchardCore.ContentFields and OrchardCore.ContentTypes);
  • CrestApps.OrchardCore.ContentFields.Address (AddressField; it brings in CrestApps.OrchardCore.Addresses).

The web host references the CrestApps.OrchardCore.ContentFields, CrestApps.OrchardCore.Addresses and CrestApps.OrchardCore.PhoneNumbers packages.

It is a managed feature, not dependency only, because a business keeps customers and vendors before any sales or purchases screen uses them; the Sales and Purchases features depend on it.

Content types​

ContactsMigrations.CreateAsync (version 1) defines three types. All are creatable, listable and securable, and neither draftable nor versionable: a contact has one version.

TypePartsFields (on the type's own part)
AlmohasebCustomerAlmohasebCustomerPart, AlmohasebCustomerAddress (AddressField, no name or company line, default country US), Phone and Mobile (PhoneField)
AlmohasebVendorAlmohasebVendorPart, AlmohasebVendorthe same three fields
AlmohasebVendorCategoryAlmohasebVendorCategoryPart

The display text of each item is set by its part driver: the company or the first and last name for a customer (ContactRules.GetCustomerName), the name for a vendor or a category.

CustomerPart​

FirstName, LastName, CompanyName, Email, PaymentTermsDays (int?, 0 to 365, null = due on receipt), Notes and IsActive.

VendorPart​

Name, CategoryId (the AlmohasebVendorCategory content item id; required, which fixes the legacy crash on a vendor without a category), Email, AccountNumber (50), PaymentTermsDays, DefaultExpenseAccountId (a ledger account of type cost of goods sold, expense, other expense, or a non-system asset), Is1099, TaxIdKind (Ein or Ssn), ProtectedTaxId, TaxIdLastFour and IsActive.

The tax ID is protected with ISensitiveDataProtector under the purpose CrestApps.Almohaseb.Contacts.VendorTaxId (ContactsConstants.TaxIdProtectionPurpose); only the last four digits are stored in clear text, for the masked display. The editor never shows the number: an empty box keeps the saved one, and Remove the saved tax ID clears it. A 1099 vendor needs a tax ID.

VendorCategoryPart​

Name, Usage (VendorCategoryUsage flags: Purchases = 1, OperatingExpenses = 2, OtherExpenses = 4, Assets = 8; the legacy "Is In ..." booleans) and IsActive.

Indexes​

ContactIndexProvider maps the latest version of each item (ContentItem.Latest) in the default collection:

IndexColumnsDatabase indexes
CustomerPartIndexContentItemId, Name (display text, 100), Email (255), IsActiveName, IsActive; ContentItemId
VendorPartIndexContentItemId, Name, CategoryId, Is1099, IsActiveName, IsActive; CategoryId, IsActive; ContentItemId
VendorCategoryPartIndexContentItemId, Name, Usage, IsActiveName; ContentItemId

The table definitions are the public static method ContactsMigrations.CreateIndexTablesAsync.

Rules​

ContactRules validates the parts without a database (ContactValidationCode):

CodeRule
NameRequiredA customer has a company, or a first and a last name; a vendor and a category have a name.
NameTooLongNames have at most 100 characters.
DuplicateNameChecked by the drivers against the index: no two customers, vendors or categories share a name.
InvalidEmailOne bare address with a dotted host (System.Net.Mail.MailAddress).
PaymentTermsOutOfRange0 to 365 days.
CategoryRequiredA vendor has a category.
AccountNumberTooLongAt most 50 characters.
InvalidTaxIdTaxIdRules.TryParse refused the number.
TaxIdRequiredFor1099A 1099 vendor has a tax ID.

TaxIdRules.TryParse(kind, value, out digits) accepts nine digits with or without dashes and spaces. An EIN goes through EmployerIdentificationNumber.TryParse (no 00 prefix). An SSN refuses the areas 000, 666 and 9xx (except ITIN middle digits 50–65, 70–88, 90–92 and 94–99), the group 00 and the serial 0000. Format writes 12-3456789 or 123-45-6789; Mask writes **-***6789 or ***-**-6789.

Services​

ServiceLifetimeWhat it does
IContactDirectory / ContactDirectoryScopedListCustomersAsync() (active customers by name) and ListVendorsAsync(usage) (active vendors of the active categories whose Usage has the flag, by name). Entry screens of other modules use it for their pickers.

Admin​

The module adds a Contacts menu group (id almohasebContacts) with Customers, Vendors and Vendor categories (ids almohasebCustomers, almohasebVendors, almohasebVendorCategories). Each item is the Orchard Core content list of its type (/Admin/Contents/ContentItems/{type}) and is shown with that type's ListContent_{type} permission. The part drivers add a ContactSummary shape to the SummaryAdmin display (e-mail, category, 1099 and inactive badges).

Permissions​

The module declares no permission of its own. The three types are securable, so the role editor lists the Orchard Core content permissions of each type (List Customer content items, Create Customer, Edit Customer for others, Delete Customer for others and so on). The Administrator role has them all.

Recipes and deployment​

Both business recipes enable CrestApps.Almohaseb.Contacts. Customers, vendors and categories are content items, so the Content recipe step and the content deployment steps import and export them; the content definitions come from the migration.

Extension points​

  • Pickers on entry screens: use IContactDirectory with the VendorCategoryUsage of the screen.
  • Editor cards: the vendor editor is Vendor, Address, Phone numbers and 1099 (the tax ID and Gets a 1099, shape AlmohasebVendorPart_Tax_Edit, with the Purchases 1099 box at Parts:4%1099;3); the customer editor is Customer, Address and Phone numbers. The module's placement.json places the address and phone fields and the part wrappers.
  • More data on a contact: attach your own part or fields to the AlmohasebCustomer or AlmohasebVendor type in a migration.

See also​