98f71d782c39571679bb3928d79d4e929c3e95f7
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
113610ea8f |
feat: WO apply_margin at fișă level + full RO/RU i18n on client portal
Two changes in one commit:
== 1. Moved apply_margin toggle from line-level to Fișă-level ==
The per-manoperă apply_margin toggle is gone from the Manopere tab.
In its place: a single "Aplică marjă internă" toggle in Fișa's
"Plată & total" section (next to override_margin_pct). One decision
per Fișă instead of per line — cleaner mental model, matches how the
shop actually thinks about at-cost vs. billable work.
Migration: work_orders.apply_margin boolean default true (idempotent).
WorkOrderWork::saving now reads WO.apply_margin from DB directly (not
via belongsTo cache) to determine salary_base:
- WO.apply_margin=false → every line gets salary_base=total, applied_margin_pct=0
- WO.apply_margin=true → resolver chain (WO.override → user margin → tenant default)
Old wo_works.apply_margin column stays untouched (backward-compat with
existing rows), but no longer exposed in UI. Tests updated to new
semantic. All existing tests green.
== 2. Full i18n audit on client-facing portal — RO/RU separated ==
Problem: user selecting Russian saw Romanian mixed into headings,
buttons, labels. Every client-facing Blade file was 100% hardcoded
Romanian — zero __() calls.
Fix: created lang/ro/portal.php + lang/ru/portal.php with 131 keys
across 3 namespaces:
- portal.common (email, phone, save, total, powered_by, ...)
- portal.invitation (welcome_name, activate_account, expired_body, ...)
- portal.tracking (title_fisa, approve, approval_needed_title,
ready_estimated, hours, unit_pcs, ...)
- portal.shop (catalog, cart, checkout_title, order_number, vin_title,
signin_title, add_to_cart, in_stock, ...)
Converted 15 Blade files to __() calls:
- resources/views/invitations/{accept,expired,invalid}.blade.php
- resources/views/tracking/show.blade.php
- resources/views/shop/{layout,catalog,cart,checkout,order,account,part,vin}.blade.php
- resources/views/shop/auth/{login,register,forgot,reset}.blade.php
Each view's <html lang="{{ app()->getLocale() }}"> now reflects the
resolved locale (was hardcoded lang="ro").
SetLocale middleware resolves locale in this order:
1. session locale (user picked via language switcher)
2. authenticated user.locale
3. tenant.settings.language
4. app.locale default (now 'ro')
Config change: config/app.php default locale + fallback both = 'ro'
(was 'en'). English falls back to Romanian for portal.* keys since
we don't ship English portal translations — a Romanian shop that
switches to English shows Romanian text, which is safer than showing
"portal.invitation.activate_account" literals.
phpunit.xml sets APP_LOCALE=ro so test assertSee() calls that look
for Romanian text pass.
Verified via portal.* grep: 131 __() calls across 15 files. Zero
hardcoded Romanian nouns/verbs left in any client-facing view.
Suite: 303 passed (840 assertions). Unchanged count — refactor,
not new tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f4ccc306dc |
feat: marjă internă — Settings % + toggle per manoperă + visibility flag
Adds three usability improvements to the marja internă feature: 1. Settings UI section "Marjă internă (nu TVA)" — configurable at tenant level 2. Per-line toggle "Aplică marjă" on each manoperă 3. Global visibility flag to hide margin details in-session == 1. Settings page == New section on /app/settings (gated by FINANCE_VIEW_INTERNAL_MARGIN): - "% marjă implicit" numeric input with % suffix, 0–90 range - "Afișează detalii marjă la procesele calculate" toggle (default on) - Explicit label "Marjă internă (nu TVA)" plus helper text explaining it's not the Moldovan tax — feeds into MarginResolver as the tenant default, applied only when the mechanic has no per-user margin. Persists as company.settings.default_internal_margin_pct and company.settings.show_internal_margin_details. == 2. Per-line "Aplică marjă" toggle == New wo_works.apply_margin boolean, default true. When false: applied_margin_pct = 0 salary_base = total (mechanic gets salaried on the full amount) Use case: oil change, tire mount, and similar "at-cost" services where the shop doesn't want to hold back part of the labor rate. The owner can flag those specific lines while keeping margin on diagnostic and premium labor. WorksRelationManager form gains a Toggle field (gated by FINANCE_VIEW_INTERNAL_MARGIN); table gains a ToggleColumn for quick inline flipping without opening the row. Booted hook now recomputes salary_base when apply_margin is dirtied, so toggling live in the table takes effect immediately. == 3. Show internal margin details flag == Global tenant flag (default on): when off, the gray subtitle line "Bază salariu: 200 · marjă 20%" under the Total column disappears for everyone, even users with FINANCE_VIEW_INTERNAL_MARGIN. Practical use: when reviewing a Fișă face-to-face with the client on the manager's screen, flip the flag off from Settings for the day → no risk of the client accidentally seeing internal numbers. Flip back when done. The flag lives in company.settings.show_internal_margin_details. == Description text on the Total column == Now shows either: - "Bază salariu: 200.00 MDL · marjă 20%" when apply_margin=true - "Fără marjă · bază salariu = Total" when apply_margin=false - nothing when show_internal_margin_details=false or role lacks permission == Tests == InternalMarginToggleTest (5): - apply_margin=false → salary_base equals total, applied_margin_pct=0 - apply_margin=true (default) still applies 20% margin - Toggling apply_margin recomputes salary_base bidirectionally - Company default margin resolves when mechanic has no per-user setting - show_internal_margin_details flag persists correctly in Company.settings Suite: 303 passed (845 assertions). Was 298. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |