teamtnt/sales-management
A Laravel package for managing sales: customers, products, orders and invoices in one place. Eloquent models, migrations and configurable workflows help you track sales activity and day-to-day transactions, and adapt the package to existing applications without rewriting your data layer.
composer require vendor/lead-activity (check the package README for the exact vendor name; service provider and facade/alias are typically auto-discovered).php artisan vendor:publish --tag=lead-activity-config and --tag=lead-activity-migrations, then php artisan migrate. As of v1.1.60 the migration set also adds preferred_contact_method and preferred_contact_time to the leads table (via the package's lead migration), so re-run migrate after upgrading.Lead model (commonly HasLeadActivities or similar) so relationships and helpers are available. Confirm preferred_contact_method and preferred_contact_time are in $fillable and cast appropriately if you publish/patch the model.preferred_contact_method, preferred_contact_time) while logging the activity, then render the activity feed, the "activity users" dropdown, and the preferred-contact summary in your CRM UI.use Vendor\LeadActivity\Models\LeadActivity;
$lead->update([
'preferred_contact_method' => 'phone',
'preferred_contact_time' => 'morning',
]);
$lead->activities()->create([
'user_id' => auth()->id(),
'type' => 'call',
'description' => 'Left voicemail',
'meta' => ['duration' => 30],
]);
Look first at:
config/lead-activity.php for table names, user model, and activity model bindings.lead_activities table (especially user_id nullability and foreign key behavior) and the lead migration for the new preferred_contact_* columns (types, nullability, defaults).ContactsController (v1.1.60 now persists preferred contact method/time from the request) and the LeadItem component, which displays those fields — both are the canonical places to change if your UI differs.LeadCreated, LeadContacted, LeadPreferenceUpdated, or LeadStatusChanged using listeners rather than sprinkling create() calls across controllers. This keeps activity records consistent and testable.$activities = $lead->activities()
->with('user')
->latest()
->paginate(25);
$userIds = LeadActivity::query()
->whereNotNull('user_id')
->whereHas('user')
->distinct()
->pluck('user_id');
$users = User::whereIn('id', $userIds)->orderBy('name')->get();
forLead($lead), byType($type), withoutOrphanedUsers(), forUser($user), and — for v1.1.60 — preferredContactMethod($method) / preferredContactTime($window) to drive filtered call lists and reporting.preferred_contact_method (phone, email, sms) and preferred_contact_time (morning, afternoon, evening), validate against it on input, and cast on the model. Raw request values from ContactsController will be stored as-is, so an unvalidated form can poison reports.preferred_contact_time, and surface the method/time in lead detail headers and list columns via LeadItem. This is the natural complement to the activity feed: activity says what happened, preferred contact says how to reach them next.LeadItem markup for preferred contact display.user_id is set correctly, that the dropdown excludes activities with null or deleted users, and that submitting a contact form persists preferred_contact_method/preferred_contact_time (and rejects invalid values).user_id = null or reference a deleted user. v1.1.59 fixes the dropdown filtering for activities without associated users, but other custom queries can still surface blank users. Add whereNotNull('user_id') and whereHas('user') anywhere you list activity users.preferred_contact_method and preferred_contact_time. Publish/re-publish migrations and run php artisan migrate; expect them to be nullable so existing leads remain valid. If you maintained a hand-rolled copy of the leads migration, diff it against the package's version before migrating.Lead model is published or heavily customized, the package's model changes won't apply — add the two attributes to $fillable (or guard them explicitly) or ContactsController updates will silently no-op.ContactsController/LeadItem overrides. If you published or extended these in earlier versions, you won't automatically receive the v1.1.60 save/display logic. Re-publish to a temp path and diff, or port the new lines manually.manifest.json was updated with new asset filenames. Rebuild assets (npm ci && npm run build), deploy the new public/build output, and clear caches (php artisan view:clear, php artisan config:clear, php artisan cache:clear). A stale manifest reference is the usual cause of "component renders but preferred contact fields are blank/missing."Rule::in([...]) for both fields; also decide whether "time" is a discrete bucket (morning/afternoon) or a timestamp, and be consistent — mixing the two will break filtering and sorting.User model uses SoftDeletes, whereHas('user') behaves according to the relation definition. Decide whether deleted users should appear in historical activity feeds; if so, define the relation with withTrashed() deliberately.user on activity lists. For dropdowns, avoid loading full activity models: use distinct()->pluck('user_id') and then query users once.lead_activities table for user_id IS NULL or IDs missing from users. Use Laravel Telescope or a quick query to find rows that would have appeared before the v1.1.59 fix.LeadItem rendering. Prefer scopes over raw queries so future package fixes are easier to adopt.How can I help you explore Laravel packages today?