feat: update profit shareing
Build & Deploy iOS to TestFlight / build-and-deploy (push) Canceled after 0s
Build & Deploy iOS to TestFlight / build-and-deploy (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,289 @@
|
|||||||
|
# Migrasi profit sharing
|
||||||
|
|
||||||
|
4 Oktober 2026
|
||||||
|
|
||||||
|
## Ringkasan
|
||||||
|
|
||||||
|
Ada tiga perubahan di backend:
|
||||||
|
|
||||||
|
1. **Parent category bisa ditandai bukan team.** Kategori punya field baru `is_team`. Parent category dengan `is_team: false` tidak bisa dipilih sebagai team di purchase order dan cash advance, dan tidak ikut laporan profit sharing.
|
||||||
|
2. **Endpoint laporan pindah path.** `/api/v1/analytics/parent-categories` menjadi `/api/v1/analytics/profit-sharing`.
|
||||||
|
3. **Pembagian revenue tinggal dua porsi.** Porsi purchase (60%) dihapus. Revenue sekarang dibagi ke owner (SDL) dan team, dengan porsi team = 100% − fee owner.
|
||||||
|
|
||||||
|
Nomor 2 dan 3 adalah breaking change. Setelah backend baru dirilis, client yang masih memanggil path lama mendapat 404, dan `limit_purchase` serta `percentages.purchase` tidak ada lagi di response. Karena itu client harus diupdate lebih dulu, lihat [Urutan rilis](#database-dan-urutan-rilis).
|
||||||
|
|
||||||
|
Yang perlu bertindak, di dashboard maupun app mobile, mana pun yang punya layarnya:
|
||||||
|
|
||||||
|
- **Form kategori**: tambah toggle team untuk parent category.
|
||||||
|
- **Laporan profit sharing**: ganti path, hapus porsi purchase, tampilkan dua porsi.
|
||||||
|
- **Form purchase order dan cash advance**: picker team tidak perlu diubah, tapi form edit perlu menyesuaikan, lihat [Purchase order dan cash advance](#purchase-order-dan-cash-advance).
|
||||||
|
|
||||||
|
## Kategori: field `is_team`
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
Semua response kategori membawa `is_team` (boolean, tidak pernah `null`): `POST /api/v1/categories`, `PUT /api/v1/categories/:id`, `GET /api/v1/categories`, dan `GET /api/v1/categories/:id`.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "<uuid>",
|
||||||
|
"name": "Merchandise",
|
||||||
|
"parent_id": null,
|
||||||
|
"owner_fee_percent": null,
|
||||||
|
"is_team": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Request
|
||||||
|
|
||||||
|
`POST /api/v1/categories` dan `PUT /api/v1/categories/:id` menerima `is_team`.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Merchandise",
|
||||||
|
"is_team": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Request | `is_team` yang dikirim | Hasil |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Create | tidak dikirim | `true` |
|
||||||
|
| Create | `false` | `false` |
|
||||||
|
| Update | tidak dikirim atau `null` | tidak berubah |
|
||||||
|
| Update | `true` atau `false` | diganti |
|
||||||
|
|
||||||
|
Update yang hanya berisi `is_team` diterima.
|
||||||
|
|
||||||
|
Aturan nilainya:
|
||||||
|
|
||||||
|
- `is_team` hanya berpengaruh di parent category, yaitu kategori dengan `parent_id: null`. Di sub-category nilainya disimpan tapi tidak dipakai, jadi tampilkan toggle hanya untuk parent category.
|
||||||
|
- Semua kategori yang sudah ada sebelum rilis bernilai `true`. Tidak ada yang berubah sampai admin mematikannya.
|
||||||
|
- Flag dibaca saat request, bukan saat transaksi. Kalau parent category dimatikan, penjualannya di periode lampau juga hilang dari laporan profit sharing. Kalau dinyalakan lagi, semuanya muncul kembali.
|
||||||
|
|
||||||
|
### Efek `is_team: false`
|
||||||
|
|
||||||
|
| Endpoint | Efek |
|
||||||
|
| --- | --- |
|
||||||
|
| `GET /api/v1/purchase-orders/teams`, `GET /api/v1/cash-advances/teams` | Kategori tidak muncul. Pusat tetap ada. |
|
||||||
|
| Create dan update purchase order dan cash advance | `team_scope: "category"` dengan `team_category_id` kategori ini ditolak. |
|
||||||
|
| `GET /api/v1/analytics/profit-sharing` | Kategori tidak muncul di `data`, dan revenue-nya tidak dihitung di `budget`. |
|
||||||
|
| `GET /api/v1/analytics/profit-sharing/:parent_category_id` | Ditolak. |
|
||||||
|
|
||||||
|
Data yang sudah ada tidak diubah. Purchase order dan cash advance yang sudah tercatat ke kategori itu tetap menyimpan team-nya. Laporan purchasing (`GET /api/v1/analytics/purchasing`) masih menampilkannya di `team_data`, dan filter `team=<category_id>` tetap bisa dipakai.
|
||||||
|
|
||||||
|
Laporan lain yang tidak menyaring `is_team`, misalnya `GET /api/v1/analytics/categories`, tetap menampilkan penjualan kategori itu.
|
||||||
|
|
||||||
|
## Purchase order dan cash advance
|
||||||
|
|
||||||
|
Picker team sudah mengambil dari `GET /api/v1/purchase-orders/teams` dan `GET /api/v1/cash-advances/teams`, jadi kategori non-team otomatis tidak muncul tanpa perubahan di client.
|
||||||
|
|
||||||
|
Yang perlu diubah ada di form edit. Purchase order atau cash advance lama bisa tercatat ke kategori yang sekarang sudah non-team. Kalau form edit mengirim ulang `team_scope` dan `team_category_id` yang sama, request ditolak, walaupun user tidak mengubah team-nya.
|
||||||
|
|
||||||
|
1. Kirim `team_scope` dan `team_category_id` hanya kalau user mengganti team. Kalau `team_scope` tidak dikirim, team yang tersimpan tidak berubah.
|
||||||
|
2. Kalau team yang tersimpan tidak ada di daftar `/teams`, tampilkan namanya dari field `team` di response apa adanya, dan jangan memilihkan team lain secara otomatis.
|
||||||
|
|
||||||
|
Contoh error saat team ditolak, dengan HTTP status 500:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"data": null,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "900",
|
||||||
|
"entity": "purchase_order_service",
|
||||||
|
"cause": "category Merchandise is not a team"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Untuk cash advance, `entity` bernilai `cash_advance_service`. Cocokkan dengan teks `is not a team` di `cause` kalau perlu menampilkan pesan khusus.
|
||||||
|
|
||||||
|
## Laporan profit sharing
|
||||||
|
|
||||||
|
### Path baru
|
||||||
|
|
||||||
|
| Lama | Baru |
|
||||||
|
| --- | --- |
|
||||||
|
| `GET /api/v1/analytics/parent-categories` | `GET /api/v1/analytics/profit-sharing` |
|
||||||
|
| `GET /api/v1/analytics/parent-categories/:parent_category_id` | `GET /api/v1/analytics/profit-sharing/:parent_category_id` |
|
||||||
|
|
||||||
|
Query parameter dan role tidak berubah:
|
||||||
|
|
||||||
|
- `date_from` dan `date_to` wajib, dengan format `DD-MM-YYYY`, misalnya `28-09-2026`.
|
||||||
|
- `outlet_id` opsional.
|
||||||
|
- Hanya bisa diakses superadmin, admin, manager, owner, dan purchasing.
|
||||||
|
|
||||||
|
Path lama sudah tidak ada dan mengembalikan 404.
|
||||||
|
|
||||||
|
### Pembagian revenue
|
||||||
|
|
||||||
|
Revenue tiap parent category yang team dibagi dua:
|
||||||
|
|
||||||
|
- **SDL (fee owner)** = revenue × `owner_fee_percent` / 100. Default-nya 20%, dan bisa diganti per parent category lewat `owner_fee_percent` di kategori.
|
||||||
|
- **Team** = revenue − SDL.
|
||||||
|
|
||||||
|
Contoh dengan tiga parent category dalam satu minggu:
|
||||||
|
|
||||||
|
| Parent category | `is_team` | Fee owner | Revenue | SDL | Team |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| Food | `true` | 20% (default) | 1.000.000 | 200.000 | 800.000 |
|
||||||
|
| Drink | `true` | 35% | 2.000.000 | 700.000 | 1.300.000 |
|
||||||
|
| Merchandise | `false` | - | 500.000 | tidak dihitung | tidak dihitung |
|
||||||
|
| **Budget minggu ini** | | | **3.000.000** | **900.000** | **2.100.000** |
|
||||||
|
|
||||||
|
### Perubahan field
|
||||||
|
|
||||||
|
| Field | Sebelum | Sesudah |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `data[]` | semua parent category | hanya parent category team |
|
||||||
|
| `budget.percentages.purchase` | `60` | dihapus |
|
||||||
|
| `budget.percentages.owner` | `20`, atau fee parent itu di endpoint detail | tidak berubah |
|
||||||
|
| `budget.percentages.team` | `20` | `100 − owner`: `80` di list, `100 − fee parent` di detail |
|
||||||
|
| `limit_purchase` di `budget.total`, `budget.weekly[]`, `budget.monthly[]` | 60% revenue | dihapus |
|
||||||
|
| `limit_team` di tempat yang sama | 20% revenue | `revenue − sdl` |
|
||||||
|
| `revenue` dan `sdl` di `budget` | semua parent category | hanya parent category team |
|
||||||
|
|
||||||
|
Di endpoint list, `budget.percentages` selalu berisi default `20` dan `80`, walaupun ada parent dengan fee berbeda. Angka `sdl` dan `limit_team` dihitung per parent dengan fee masing-masing, jadi `limit_team / revenue` bisa tidak persis 80%. Tampilkan angka rupiah dari response, jangan dihitung ulang dari persentase.
|
||||||
|
|
||||||
|
Baris di `data[]` membawa `sdl` tapi tidak membawa porsi team. Kalau porsi team per parent perlu ditampilkan, hitung dari `total_revenue − sdl`.
|
||||||
|
|
||||||
|
Contoh response list, dipotong:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"date_from": "2026-09-28T00:00:00+07:00",
|
||||||
|
"date_to": "2026-10-04T23:59:59.999999999+07:00",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"parent_category_id": "<uuid>",
|
||||||
|
"parent_category_name": "Drink",
|
||||||
|
"owner_fee_percent": 35,
|
||||||
|
"sdl": 700000,
|
||||||
|
"total_revenue": 2000000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parent_category_id": "<uuid>",
|
||||||
|
"parent_category_name": "Food",
|
||||||
|
"owner_fee_percent": 20,
|
||||||
|
"sdl": 200000,
|
||||||
|
"total_revenue": 1000000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"budget": {
|
||||||
|
"percentages": { "owner": 20, "team": 80 },
|
||||||
|
"cut_off_from": "2026-09-28T00:00:00+07:00",
|
||||||
|
"cut_off_to": "2026-10-04T23:59:59.999999999+07:00",
|
||||||
|
"total": {
|
||||||
|
"period_start": "2026-09-28T00:00:00+07:00",
|
||||||
|
"period_end": "2026-10-04T23:59:59.999999999+07:00",
|
||||||
|
"revenue": 3000000,
|
||||||
|
"order_count": 4,
|
||||||
|
"sdl": 900000,
|
||||||
|
"limit_team": 2100000
|
||||||
|
},
|
||||||
|
"weekly": [
|
||||||
|
{
|
||||||
|
"period_start": "2026-09-28T00:00:00+07:00",
|
||||||
|
"period_end": "2026-10-04T23:59:59.999999999+07:00",
|
||||||
|
"revenue": 3000000,
|
||||||
|
"order_count": 4,
|
||||||
|
"sdl": 900000,
|
||||||
|
"limit_team": 2100000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"monthly": [
|
||||||
|
{
|
||||||
|
"month": "2026-09",
|
||||||
|
"week_count": 1,
|
||||||
|
"period_start": "2026-09-28T00:00:00+07:00",
|
||||||
|
"period_end": "2026-10-04T23:59:59.999999999+07:00",
|
||||||
|
"revenue": 3000000,
|
||||||
|
"order_count": 4,
|
||||||
|
"sdl": 900000,
|
||||||
|
"limit_team": 2100000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Di endpoint detail, `budget` bentuknya sama, tapi `percentages` memakai fee parent itu, misalnya `{ "owner": 35, "team": 65 }` untuk Drink.
|
||||||
|
|
||||||
|
### Detail kategori non-team
|
||||||
|
|
||||||
|
Detail untuk parent category non-team ditolak dengan HTTP status 500:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"data": null,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "internal_error",
|
||||||
|
"entity": "AnalyticsHandler::GetParentCategoryAnalyticsDetail",
|
||||||
|
"cause": "failed to get parent category analytics detail: failed to get parent category analytics detail: category Merchandise is not a team"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ini bisa terjadi kalau user membuka link lama atau bookmark ke parent yang baru dimatikan. Cocokkan dengan teks `is not a team` di `cause`, lalu arahkan user kembali ke list.
|
||||||
|
|
||||||
|
## Migrasi client
|
||||||
|
|
||||||
|
### Laporan profit sharing
|
||||||
|
|
||||||
|
1. Ganti path ke `/api/v1/analytics/profit-sharing`. Selama backend lama masih jalan, path baru mengembalikan 404. Kalau dapat 404, panggil path lama `/api/v1/analytics/parent-categories`, supaya client baru bisa dirilis sebelum backend.
|
||||||
|
2. Hapus tampilan limit purchase dan persentase purchase. Jangan menganggap `limit_purchase` atau `percentages.purchase` selalu ada.
|
||||||
|
3. Tampilkan dua porsi dengan label "SDL / Fee owner" dan "Team", ambil angkanya dari `sdl` dan `limit_team`.
|
||||||
|
4. Kalau detail ditolak dengan `is not a team`, arahkan kembali ke list.
|
||||||
|
|
||||||
|
Selama fallback ke backend lama, `limit_team` masih berisi 20% revenue. Angkanya baru jadi `revenue − sdl` setelah backend baru dirilis.
|
||||||
|
|
||||||
|
### Form kategori
|
||||||
|
|
||||||
|
1. Tambah toggle `is_team` untuk parent category, misalnya berlabel "Ikut profit sharing (team)". Untuk kategori baru, toggle menyala secara default.
|
||||||
|
2. Saat membuka form edit, isi toggle dari `is_team`. Selama backend lama masih jalan, field ini tidak ada di response, jadi anggap `true`.
|
||||||
|
3. Saat admin mematikan toggle, tampilkan konfirmasi bahwa kategori itu tidak akan muncul di pilihan team dan di laporan profit sharing, termasuk untuk periode lampau.
|
||||||
|
4. Di daftar kategori, beri penanda untuk parent category dengan `is_team: false`.
|
||||||
|
|
||||||
|
Backend lama mengabaikan `is_team` di request, jadi toggle bisa dirilis lebih dulu, tapi belum berpengaruh sampai backend baru jalan. Pengecualiannya update yang hanya berisi `is_team`: backend lama menolaknya dengan error code `303` dan pesan `at least one field must be provided for update`. Selama masa transisi, kirim `is_team` bersama field form lainnya.
|
||||||
|
|
||||||
|
## Database dan urutan rilis
|
||||||
|
|
||||||
|
Migration `000101_add_is_team_to_categories` menambah kolom `categories.is_team` (`BOOLEAN NOT NULL DEFAULT TRUE`). Semua kategori yang ada otomatis bernilai `true`. Migration ini hanya menambah kolom, jadi backend lama tetap jalan normal setelahnya.
|
||||||
|
|
||||||
|
Urutan rilis:
|
||||||
|
|
||||||
|
1. Rilis client baru: path profit sharing dengan fallback ke path lama, tanpa porsi purchase, dan dengan toggle `is_team`. Untuk app mobile, pastikan versi baru sudah dipakai sebagian besar user sebelum langkah 3, karena versi lama yang memanggil `/parent-categories` mendapat 404 setelah itu.
|
||||||
|
2. Jalankan migration `000101`.
|
||||||
|
3. Deploy backend baru.
|
||||||
|
4. Hapus fallback path lama di client.
|
||||||
|
5. Admin mematikan `is_team` di parent category yang bukan team.
|
||||||
|
|
||||||
|
Rollback: deploy backend lama, lalu jalankan down migration yang menghapus kolom `is_team`. Client dengan fallback tetap jalan di backend lama. Nilai `is_team` yang sudah diatur admin hilang saat kolom dihapus.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Client baru (fallback path, tanpa porsi purchase, toggle `is_team`) dirilis
|
||||||
|
- [ ] Migration `000101` dan backend baru dirilis di staging
|
||||||
|
- [ ] Uji: parent category yang dimatikan hilang dari `/purchase-orders/teams` dan `/cash-advances/teams`
|
||||||
|
- [ ] Uji: purchase order dan cash advance baru dengan kategori itu ditolak, dan edit purchase order lama tanpa mengganti team tetap berhasil
|
||||||
|
- [ ] Uji: kategori itu hilang dari `/analytics/profit-sharing`, dan detailnya ditolak
|
||||||
|
- [ ] Uji: `limit_team = revenue − sdl`, dan `sdl` mengikuti fee masing-masing parent
|
||||||
|
- [ ] Migration `000101` dan backend baru dirilis di production
|
||||||
|
- [ ] Fallback path lama di client dihapus
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
**Kenapa porsi team jadi 100% − fee owner, bukan tetap 20%?** Porsi purchase sudah tidak ada, jadi seluruh revenue dibagi dua. Owner mengambil fee-nya, dan sisanya untuk team. Kalau fee owner sebuah parent dinaikkan, porsi team parent itu turun sebesar yang sama.
|
||||||
|
|
||||||
|
**Apakah sub-category bisa dijadikan non-team sendiri?** Tidak. Team dan profit sharing dihitung per parent category, jadi semua sub-category ikut status parent-nya.
|
||||||
|
|
||||||
|
**Bagaimana dengan kategori top-level yang tidak punya sub-category?** Kategori itu tetap parent category, jadi `is_team` berlaku untuknya.
|
||||||
@@ -14,7 +14,12 @@ class ApiPath {
|
|||||||
static const String purchasingAnalytic = '/api/v1/analytics/purchasing';
|
static const String purchasingAnalytic = '/api/v1/analytics/purchasing';
|
||||||
static const String exclusiveSummaryAnalytic =
|
static const String exclusiveSummaryAnalytic =
|
||||||
'/api/v1/analytics/exclusive-summary/period';
|
'/api/v1/analytics/exclusive-summary/period';
|
||||||
static const String parentCategoryAnalytic =
|
static const String profitSharingAnalytic =
|
||||||
|
'/api/v1/analytics/profit-sharing';
|
||||||
|
|
||||||
|
/// Path lama profit sharing, hanya untuk fallback selama backend lama masih
|
||||||
|
/// jalan. Hapus setelah backend baru rilis (docs/migrasi-profit-sharing.md).
|
||||||
|
static const String profitSharingAnalyticLegacy =
|
||||||
'/api/v1/analytics/parent-categories';
|
'/api/v1/analytics/parent-categories';
|
||||||
|
|
||||||
// Inventory
|
// Inventory
|
||||||
|
|||||||
@@ -13342,7 +13342,6 @@ abstract class _ProfitSharingBudget implements ProfitSharingBudget {
|
|||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$ProfitSharingPercentage {
|
mixin _$ProfitSharingPercentage {
|
||||||
double get purchase => throw _privateConstructorUsedError;
|
|
||||||
double get owner => throw _privateConstructorUsedError;
|
double get owner => throw _privateConstructorUsedError;
|
||||||
double get team => throw _privateConstructorUsedError;
|
double get team => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
@@ -13360,7 +13359,7 @@ abstract class $ProfitSharingPercentageCopyWith<$Res> {
|
|||||||
$Res Function(ProfitSharingPercentage) then,
|
$Res Function(ProfitSharingPercentage) then,
|
||||||
) = _$ProfitSharingPercentageCopyWithImpl<$Res, ProfitSharingPercentage>;
|
) = _$ProfitSharingPercentageCopyWithImpl<$Res, ProfitSharingPercentage>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({double purchase, double owner, double team});
|
$Res call({double owner, double team});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -13380,17 +13379,9 @@ class _$ProfitSharingPercentageCopyWithImpl<
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({Object? owner = null, Object? team = null}) {
|
||||||
Object? purchase = null,
|
|
||||||
Object? owner = null,
|
|
||||||
Object? team = null,
|
|
||||||
}) {
|
|
||||||
return _then(
|
return _then(
|
||||||
_value.copyWith(
|
_value.copyWith(
|
||||||
purchase: null == purchase
|
|
||||||
? _value.purchase
|
|
||||||
: purchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double,
|
|
||||||
owner: null == owner
|
owner: null == owner
|
||||||
? _value.owner
|
? _value.owner
|
||||||
: owner // ignore: cast_nullable_to_non_nullable
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -13414,7 +13405,7 @@ abstract class _$$ProfitSharingPercentageImplCopyWith<$Res>
|
|||||||
) = __$$ProfitSharingPercentageImplCopyWithImpl<$Res>;
|
) = __$$ProfitSharingPercentageImplCopyWithImpl<$Res>;
|
||||||
@override
|
@override
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({double purchase, double owner, double team});
|
$Res call({double owner, double team});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -13434,17 +13425,9 @@ class __$$ProfitSharingPercentageImplCopyWithImpl<$Res>
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({Object? owner = null, Object? team = null}) {
|
||||||
Object? purchase = null,
|
|
||||||
Object? owner = null,
|
|
||||||
Object? team = null,
|
|
||||||
}) {
|
|
||||||
return _then(
|
return _then(
|
||||||
_$ProfitSharingPercentageImpl(
|
_$ProfitSharingPercentageImpl(
|
||||||
purchase: null == purchase
|
|
||||||
? _value.purchase
|
|
||||||
: purchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double,
|
|
||||||
owner: null == owner
|
owner: null == owner
|
||||||
? _value.owner
|
? _value.owner
|
||||||
: owner // ignore: cast_nullable_to_non_nullable
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -13462,13 +13445,10 @@ class __$$ProfitSharingPercentageImplCopyWithImpl<$Res>
|
|||||||
|
|
||||||
class _$ProfitSharingPercentageImpl implements _ProfitSharingPercentage {
|
class _$ProfitSharingPercentageImpl implements _ProfitSharingPercentage {
|
||||||
const _$ProfitSharingPercentageImpl({
|
const _$ProfitSharingPercentageImpl({
|
||||||
required this.purchase,
|
|
||||||
required this.owner,
|
required this.owner,
|
||||||
required this.team,
|
required this.team,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
|
||||||
final double purchase;
|
|
||||||
@override
|
@override
|
||||||
final double owner;
|
final double owner;
|
||||||
@override
|
@override
|
||||||
@@ -13476,7 +13456,7 @@ class _$ProfitSharingPercentageImpl implements _ProfitSharingPercentage {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ProfitSharingPercentage(purchase: $purchase, owner: $owner, team: $team)';
|
return 'ProfitSharingPercentage(owner: $owner, team: $team)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -13484,14 +13464,12 @@ class _$ProfitSharingPercentageImpl implements _ProfitSharingPercentage {
|
|||||||
return identical(this, other) ||
|
return identical(this, other) ||
|
||||||
(other.runtimeType == runtimeType &&
|
(other.runtimeType == runtimeType &&
|
||||||
other is _$ProfitSharingPercentageImpl &&
|
other is _$ProfitSharingPercentageImpl &&
|
||||||
(identical(other.purchase, purchase) ||
|
|
||||||
other.purchase == purchase) &&
|
|
||||||
(identical(other.owner, owner) || other.owner == owner) &&
|
(identical(other.owner, owner) || other.owner == owner) &&
|
||||||
(identical(other.team, team) || other.team == team));
|
(identical(other.team, team) || other.team == team));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, purchase, owner, team);
|
int get hashCode => Object.hash(runtimeType, owner, team);
|
||||||
|
|
||||||
/// Create a copy of ProfitSharingPercentage
|
/// Create a copy of ProfitSharingPercentage
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -13507,13 +13485,10 @@ class _$ProfitSharingPercentageImpl implements _ProfitSharingPercentage {
|
|||||||
|
|
||||||
abstract class _ProfitSharingPercentage implements ProfitSharingPercentage {
|
abstract class _ProfitSharingPercentage implements ProfitSharingPercentage {
|
||||||
const factory _ProfitSharingPercentage({
|
const factory _ProfitSharingPercentage({
|
||||||
required final double purchase,
|
|
||||||
required final double owner,
|
required final double owner,
|
||||||
required final double team,
|
required final double team,
|
||||||
}) = _$ProfitSharingPercentageImpl;
|
}) = _$ProfitSharingPercentageImpl;
|
||||||
|
|
||||||
@override
|
|
||||||
double get purchase;
|
|
||||||
@override
|
@override
|
||||||
double get owner;
|
double get owner;
|
||||||
@override
|
@override
|
||||||
@@ -13533,7 +13508,6 @@ mixin _$ProfitSharingPeriod {
|
|||||||
DateTime get periodEnd => throw _privateConstructorUsedError;
|
DateTime get periodEnd => throw _privateConstructorUsedError;
|
||||||
int get revenue => throw _privateConstructorUsedError;
|
int get revenue => throw _privateConstructorUsedError;
|
||||||
int get orderCount => throw _privateConstructorUsedError;
|
int get orderCount => throw _privateConstructorUsedError;
|
||||||
int get limitPurchase => throw _privateConstructorUsedError;
|
|
||||||
int get sdl => throw _privateConstructorUsedError;
|
int get sdl => throw _privateConstructorUsedError;
|
||||||
int get limitTeam => throw _privateConstructorUsedError;
|
int get limitTeam => throw _privateConstructorUsedError;
|
||||||
String get month => throw _privateConstructorUsedError;
|
String get month => throw _privateConstructorUsedError;
|
||||||
@@ -13558,7 +13532,6 @@ abstract class $ProfitSharingPeriodCopyWith<$Res> {
|
|||||||
DateTime periodEnd,
|
DateTime periodEnd,
|
||||||
int revenue,
|
int revenue,
|
||||||
int orderCount,
|
int orderCount,
|
||||||
int limitPurchase,
|
|
||||||
int sdl,
|
int sdl,
|
||||||
int limitTeam,
|
int limitTeam,
|
||||||
String month,
|
String month,
|
||||||
@@ -13585,7 +13558,6 @@ class _$ProfitSharingPeriodCopyWithImpl<$Res, $Val extends ProfitSharingPeriod>
|
|||||||
Object? periodEnd = null,
|
Object? periodEnd = null,
|
||||||
Object? revenue = null,
|
Object? revenue = null,
|
||||||
Object? orderCount = null,
|
Object? orderCount = null,
|
||||||
Object? limitPurchase = null,
|
|
||||||
Object? sdl = null,
|
Object? sdl = null,
|
||||||
Object? limitTeam = null,
|
Object? limitTeam = null,
|
||||||
Object? month = null,
|
Object? month = null,
|
||||||
@@ -13609,10 +13581,6 @@ class _$ProfitSharingPeriodCopyWithImpl<$Res, $Val extends ProfitSharingPeriod>
|
|||||||
? _value.orderCount
|
? _value.orderCount
|
||||||
: orderCount // ignore: cast_nullable_to_non_nullable
|
: orderCount // ignore: cast_nullable_to_non_nullable
|
||||||
as int,
|
as int,
|
||||||
limitPurchase: null == limitPurchase
|
|
||||||
? _value.limitPurchase
|
|
||||||
: limitPurchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as int,
|
|
||||||
sdl: null == sdl
|
sdl: null == sdl
|
||||||
? _value.sdl
|
? _value.sdl
|
||||||
: sdl // ignore: cast_nullable_to_non_nullable
|
: sdl // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -13649,7 +13617,6 @@ abstract class _$$ProfitSharingPeriodImplCopyWith<$Res>
|
|||||||
DateTime periodEnd,
|
DateTime periodEnd,
|
||||||
int revenue,
|
int revenue,
|
||||||
int orderCount,
|
int orderCount,
|
||||||
int limitPurchase,
|
|
||||||
int sdl,
|
int sdl,
|
||||||
int limitTeam,
|
int limitTeam,
|
||||||
String month,
|
String month,
|
||||||
@@ -13675,7 +13642,6 @@ class __$$ProfitSharingPeriodImplCopyWithImpl<$Res>
|
|||||||
Object? periodEnd = null,
|
Object? periodEnd = null,
|
||||||
Object? revenue = null,
|
Object? revenue = null,
|
||||||
Object? orderCount = null,
|
Object? orderCount = null,
|
||||||
Object? limitPurchase = null,
|
|
||||||
Object? sdl = null,
|
Object? sdl = null,
|
||||||
Object? limitTeam = null,
|
Object? limitTeam = null,
|
||||||
Object? month = null,
|
Object? month = null,
|
||||||
@@ -13699,10 +13665,6 @@ class __$$ProfitSharingPeriodImplCopyWithImpl<$Res>
|
|||||||
? _value.orderCount
|
? _value.orderCount
|
||||||
: orderCount // ignore: cast_nullable_to_non_nullable
|
: orderCount // ignore: cast_nullable_to_non_nullable
|
||||||
as int,
|
as int,
|
||||||
limitPurchase: null == limitPurchase
|
|
||||||
? _value.limitPurchase
|
|
||||||
: limitPurchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as int,
|
|
||||||
sdl: null == sdl
|
sdl: null == sdl
|
||||||
? _value.sdl
|
? _value.sdl
|
||||||
: sdl // ignore: cast_nullable_to_non_nullable
|
: sdl // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -13732,7 +13694,6 @@ class _$ProfitSharingPeriodImpl extends _ProfitSharingPeriod {
|
|||||||
required this.periodEnd,
|
required this.periodEnd,
|
||||||
required this.revenue,
|
required this.revenue,
|
||||||
required this.orderCount,
|
required this.orderCount,
|
||||||
required this.limitPurchase,
|
|
||||||
required this.sdl,
|
required this.sdl,
|
||||||
required this.limitTeam,
|
required this.limitTeam,
|
||||||
this.month = '',
|
this.month = '',
|
||||||
@@ -13748,8 +13709,6 @@ class _$ProfitSharingPeriodImpl extends _ProfitSharingPeriod {
|
|||||||
@override
|
@override
|
||||||
final int orderCount;
|
final int orderCount;
|
||||||
@override
|
@override
|
||||||
final int limitPurchase;
|
|
||||||
@override
|
|
||||||
final int sdl;
|
final int sdl;
|
||||||
@override
|
@override
|
||||||
final int limitTeam;
|
final int limitTeam;
|
||||||
@@ -13762,7 +13721,7 @@ class _$ProfitSharingPeriodImpl extends _ProfitSharingPeriod {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ProfitSharingPeriod(periodStart: $periodStart, periodEnd: $periodEnd, revenue: $revenue, orderCount: $orderCount, limitPurchase: $limitPurchase, sdl: $sdl, limitTeam: $limitTeam, month: $month, weekCount: $weekCount)';
|
return 'ProfitSharingPeriod(periodStart: $periodStart, periodEnd: $periodEnd, revenue: $revenue, orderCount: $orderCount, sdl: $sdl, limitTeam: $limitTeam, month: $month, weekCount: $weekCount)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -13777,8 +13736,6 @@ class _$ProfitSharingPeriodImpl extends _ProfitSharingPeriod {
|
|||||||
(identical(other.revenue, revenue) || other.revenue == revenue) &&
|
(identical(other.revenue, revenue) || other.revenue == revenue) &&
|
||||||
(identical(other.orderCount, orderCount) ||
|
(identical(other.orderCount, orderCount) ||
|
||||||
other.orderCount == orderCount) &&
|
other.orderCount == orderCount) &&
|
||||||
(identical(other.limitPurchase, limitPurchase) ||
|
|
||||||
other.limitPurchase == limitPurchase) &&
|
|
||||||
(identical(other.sdl, sdl) || other.sdl == sdl) &&
|
(identical(other.sdl, sdl) || other.sdl == sdl) &&
|
||||||
(identical(other.limitTeam, limitTeam) ||
|
(identical(other.limitTeam, limitTeam) ||
|
||||||
other.limitTeam == limitTeam) &&
|
other.limitTeam == limitTeam) &&
|
||||||
@@ -13794,7 +13751,6 @@ class _$ProfitSharingPeriodImpl extends _ProfitSharingPeriod {
|
|||||||
periodEnd,
|
periodEnd,
|
||||||
revenue,
|
revenue,
|
||||||
orderCount,
|
orderCount,
|
||||||
limitPurchase,
|
|
||||||
sdl,
|
sdl,
|
||||||
limitTeam,
|
limitTeam,
|
||||||
month,
|
month,
|
||||||
@@ -13819,7 +13775,6 @@ abstract class _ProfitSharingPeriod extends ProfitSharingPeriod {
|
|||||||
required final DateTime periodEnd,
|
required final DateTime periodEnd,
|
||||||
required final int revenue,
|
required final int revenue,
|
||||||
required final int orderCount,
|
required final int orderCount,
|
||||||
required final int limitPurchase,
|
|
||||||
required final int sdl,
|
required final int sdl,
|
||||||
required final int limitTeam,
|
required final int limitTeam,
|
||||||
final String month,
|
final String month,
|
||||||
@@ -13836,8 +13791,6 @@ abstract class _ProfitSharingPeriod extends ProfitSharingPeriod {
|
|||||||
@override
|
@override
|
||||||
int get orderCount;
|
int get orderCount;
|
||||||
@override
|
@override
|
||||||
int get limitPurchase;
|
|
||||||
@override
|
|
||||||
int get sdl;
|
int get sdl;
|
||||||
@override
|
@override
|
||||||
int get limitTeam;
|
int get limitTeam;
|
||||||
@@ -15050,6 +15003,7 @@ mixin _$AnalyticFailure {
|
|||||||
required TResult Function(ApiFailure failure) serverError,
|
required TResult Function(ApiFailure failure) serverError,
|
||||||
required TResult Function() unexpectedError,
|
required TResult Function() unexpectedError,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
|
required TResult Function() notTeam,
|
||||||
required TResult Function(String erroMessage) dynamicErrorMessage,
|
required TResult Function(String erroMessage) dynamicErrorMessage,
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
@@ -15057,6 +15011,7 @@ mixin _$AnalyticFailure {
|
|||||||
TResult? Function(ApiFailure failure)? serverError,
|
TResult? Function(ApiFailure failure)? serverError,
|
||||||
TResult? Function()? unexpectedError,
|
TResult? Function()? unexpectedError,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
|
TResult? Function()? notTeam,
|
||||||
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
@@ -15064,6 +15019,7 @@ mixin _$AnalyticFailure {
|
|||||||
TResult Function(ApiFailure failure)? serverError,
|
TResult Function(ApiFailure failure)? serverError,
|
||||||
TResult Function()? unexpectedError,
|
TResult Function()? unexpectedError,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
|
TResult Function()? notTeam,
|
||||||
TResult Function(String erroMessage)? dynamicErrorMessage,
|
TResult Function(String erroMessage)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@@ -15072,6 +15028,7 @@ mixin _$AnalyticFailure {
|
|||||||
required TResult Function(_ServerError value) serverError,
|
required TResult Function(_ServerError value) serverError,
|
||||||
required TResult Function(_UnexpectedError value) unexpectedError,
|
required TResult Function(_UnexpectedError value) unexpectedError,
|
||||||
required TResult Function(_Empty value) empty,
|
required TResult Function(_Empty value) empty,
|
||||||
|
required TResult Function(_NotTeam value) notTeam,
|
||||||
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
@@ -15079,6 +15036,7 @@ mixin _$AnalyticFailure {
|
|||||||
TResult? Function(_ServerError value)? serverError,
|
TResult? Function(_ServerError value)? serverError,
|
||||||
TResult? Function(_UnexpectedError value)? unexpectedError,
|
TResult? Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult? Function(_Empty value)? empty,
|
TResult? Function(_Empty value)? empty,
|
||||||
|
TResult? Function(_NotTeam value)? notTeam,
|
||||||
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
@@ -15086,6 +15044,7 @@ mixin _$AnalyticFailure {
|
|||||||
TResult Function(_ServerError value)? serverError,
|
TResult Function(_ServerError value)? serverError,
|
||||||
TResult Function(_UnexpectedError value)? unexpectedError,
|
TResult Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult Function(_Empty value)? empty,
|
TResult Function(_Empty value)? empty,
|
||||||
|
TResult Function(_NotTeam value)? notTeam,
|
||||||
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@@ -15198,6 +15157,7 @@ class _$ServerErrorImpl implements _ServerError {
|
|||||||
required TResult Function(ApiFailure failure) serverError,
|
required TResult Function(ApiFailure failure) serverError,
|
||||||
required TResult Function() unexpectedError,
|
required TResult Function() unexpectedError,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
|
required TResult Function() notTeam,
|
||||||
required TResult Function(String erroMessage) dynamicErrorMessage,
|
required TResult Function(String erroMessage) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return serverError(failure);
|
return serverError(failure);
|
||||||
@@ -15209,6 +15169,7 @@ class _$ServerErrorImpl implements _ServerError {
|
|||||||
TResult? Function(ApiFailure failure)? serverError,
|
TResult? Function(ApiFailure failure)? serverError,
|
||||||
TResult? Function()? unexpectedError,
|
TResult? Function()? unexpectedError,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
|
TResult? Function()? notTeam,
|
||||||
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return serverError?.call(failure);
|
return serverError?.call(failure);
|
||||||
@@ -15220,6 +15181,7 @@ class _$ServerErrorImpl implements _ServerError {
|
|||||||
TResult Function(ApiFailure failure)? serverError,
|
TResult Function(ApiFailure failure)? serverError,
|
||||||
TResult Function()? unexpectedError,
|
TResult Function()? unexpectedError,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
|
TResult Function()? notTeam,
|
||||||
TResult Function(String erroMessage)? dynamicErrorMessage,
|
TResult Function(String erroMessage)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -15235,6 +15197,7 @@ class _$ServerErrorImpl implements _ServerError {
|
|||||||
required TResult Function(_ServerError value) serverError,
|
required TResult Function(_ServerError value) serverError,
|
||||||
required TResult Function(_UnexpectedError value) unexpectedError,
|
required TResult Function(_UnexpectedError value) unexpectedError,
|
||||||
required TResult Function(_Empty value) empty,
|
required TResult Function(_Empty value) empty,
|
||||||
|
required TResult Function(_NotTeam value) notTeam,
|
||||||
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return serverError(this);
|
return serverError(this);
|
||||||
@@ -15246,6 +15209,7 @@ class _$ServerErrorImpl implements _ServerError {
|
|||||||
TResult? Function(_ServerError value)? serverError,
|
TResult? Function(_ServerError value)? serverError,
|
||||||
TResult? Function(_UnexpectedError value)? unexpectedError,
|
TResult? Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult? Function(_Empty value)? empty,
|
TResult? Function(_Empty value)? empty,
|
||||||
|
TResult? Function(_NotTeam value)? notTeam,
|
||||||
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return serverError?.call(this);
|
return serverError?.call(this);
|
||||||
@@ -15257,6 +15221,7 @@ class _$ServerErrorImpl implements _ServerError {
|
|||||||
TResult Function(_ServerError value)? serverError,
|
TResult Function(_ServerError value)? serverError,
|
||||||
TResult Function(_UnexpectedError value)? unexpectedError,
|
TResult Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult Function(_Empty value)? empty,
|
TResult Function(_Empty value)? empty,
|
||||||
|
TResult Function(_NotTeam value)? notTeam,
|
||||||
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -15325,6 +15290,7 @@ class _$UnexpectedErrorImpl implements _UnexpectedError {
|
|||||||
required TResult Function(ApiFailure failure) serverError,
|
required TResult Function(ApiFailure failure) serverError,
|
||||||
required TResult Function() unexpectedError,
|
required TResult Function() unexpectedError,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
|
required TResult Function() notTeam,
|
||||||
required TResult Function(String erroMessage) dynamicErrorMessage,
|
required TResult Function(String erroMessage) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return unexpectedError();
|
return unexpectedError();
|
||||||
@@ -15336,6 +15302,7 @@ class _$UnexpectedErrorImpl implements _UnexpectedError {
|
|||||||
TResult? Function(ApiFailure failure)? serverError,
|
TResult? Function(ApiFailure failure)? serverError,
|
||||||
TResult? Function()? unexpectedError,
|
TResult? Function()? unexpectedError,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
|
TResult? Function()? notTeam,
|
||||||
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return unexpectedError?.call();
|
return unexpectedError?.call();
|
||||||
@@ -15347,6 +15314,7 @@ class _$UnexpectedErrorImpl implements _UnexpectedError {
|
|||||||
TResult Function(ApiFailure failure)? serverError,
|
TResult Function(ApiFailure failure)? serverError,
|
||||||
TResult Function()? unexpectedError,
|
TResult Function()? unexpectedError,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
|
TResult Function()? notTeam,
|
||||||
TResult Function(String erroMessage)? dynamicErrorMessage,
|
TResult Function(String erroMessage)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -15362,6 +15330,7 @@ class _$UnexpectedErrorImpl implements _UnexpectedError {
|
|||||||
required TResult Function(_ServerError value) serverError,
|
required TResult Function(_ServerError value) serverError,
|
||||||
required TResult Function(_UnexpectedError value) unexpectedError,
|
required TResult Function(_UnexpectedError value) unexpectedError,
|
||||||
required TResult Function(_Empty value) empty,
|
required TResult Function(_Empty value) empty,
|
||||||
|
required TResult Function(_NotTeam value) notTeam,
|
||||||
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return unexpectedError(this);
|
return unexpectedError(this);
|
||||||
@@ -15373,6 +15342,7 @@ class _$UnexpectedErrorImpl implements _UnexpectedError {
|
|||||||
TResult? Function(_ServerError value)? serverError,
|
TResult? Function(_ServerError value)? serverError,
|
||||||
TResult? Function(_UnexpectedError value)? unexpectedError,
|
TResult? Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult? Function(_Empty value)? empty,
|
TResult? Function(_Empty value)? empty,
|
||||||
|
TResult? Function(_NotTeam value)? notTeam,
|
||||||
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return unexpectedError?.call(this);
|
return unexpectedError?.call(this);
|
||||||
@@ -15384,6 +15354,7 @@ class _$UnexpectedErrorImpl implements _UnexpectedError {
|
|||||||
TResult Function(_ServerError value)? serverError,
|
TResult Function(_ServerError value)? serverError,
|
||||||
TResult Function(_UnexpectedError value)? unexpectedError,
|
TResult Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult Function(_Empty value)? empty,
|
TResult Function(_Empty value)? empty,
|
||||||
|
TResult Function(_NotTeam value)? notTeam,
|
||||||
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -15444,6 +15415,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
required TResult Function(ApiFailure failure) serverError,
|
required TResult Function(ApiFailure failure) serverError,
|
||||||
required TResult Function() unexpectedError,
|
required TResult Function() unexpectedError,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
|
required TResult Function() notTeam,
|
||||||
required TResult Function(String erroMessage) dynamicErrorMessage,
|
required TResult Function(String erroMessage) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return empty();
|
return empty();
|
||||||
@@ -15455,6 +15427,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
TResult? Function(ApiFailure failure)? serverError,
|
TResult? Function(ApiFailure failure)? serverError,
|
||||||
TResult? Function()? unexpectedError,
|
TResult? Function()? unexpectedError,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
|
TResult? Function()? notTeam,
|
||||||
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return empty?.call();
|
return empty?.call();
|
||||||
@@ -15466,6 +15439,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
TResult Function(ApiFailure failure)? serverError,
|
TResult Function(ApiFailure failure)? serverError,
|
||||||
TResult Function()? unexpectedError,
|
TResult Function()? unexpectedError,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
|
TResult Function()? notTeam,
|
||||||
TResult Function(String erroMessage)? dynamicErrorMessage,
|
TResult Function(String erroMessage)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -15481,6 +15455,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
required TResult Function(_ServerError value) serverError,
|
required TResult Function(_ServerError value) serverError,
|
||||||
required TResult Function(_UnexpectedError value) unexpectedError,
|
required TResult Function(_UnexpectedError value) unexpectedError,
|
||||||
required TResult Function(_Empty value) empty,
|
required TResult Function(_Empty value) empty,
|
||||||
|
required TResult Function(_NotTeam value) notTeam,
|
||||||
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return empty(this);
|
return empty(this);
|
||||||
@@ -15492,6 +15467,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
TResult? Function(_ServerError value)? serverError,
|
TResult? Function(_ServerError value)? serverError,
|
||||||
TResult? Function(_UnexpectedError value)? unexpectedError,
|
TResult? Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult? Function(_Empty value)? empty,
|
TResult? Function(_Empty value)? empty,
|
||||||
|
TResult? Function(_NotTeam value)? notTeam,
|
||||||
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return empty?.call(this);
|
return empty?.call(this);
|
||||||
@@ -15503,6 +15479,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
TResult Function(_ServerError value)? serverError,
|
TResult Function(_ServerError value)? serverError,
|
||||||
TResult Function(_UnexpectedError value)? unexpectedError,
|
TResult Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult Function(_Empty value)? empty,
|
TResult Function(_Empty value)? empty,
|
||||||
|
TResult Function(_NotTeam value)? notTeam,
|
||||||
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -15517,6 +15494,131 @@ abstract class _Empty implements AnalyticFailure {
|
|||||||
const factory _Empty() = _$EmptyImpl;
|
const factory _Empty() = _$EmptyImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$NotTeamImplCopyWith<$Res> {
|
||||||
|
factory _$$NotTeamImplCopyWith(
|
||||||
|
_$NotTeamImpl value,
|
||||||
|
$Res Function(_$NotTeamImpl) then,
|
||||||
|
) = __$$NotTeamImplCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$NotTeamImplCopyWithImpl<$Res>
|
||||||
|
extends _$AnalyticFailureCopyWithImpl<$Res, _$NotTeamImpl>
|
||||||
|
implements _$$NotTeamImplCopyWith<$Res> {
|
||||||
|
__$$NotTeamImplCopyWithImpl(
|
||||||
|
_$NotTeamImpl _value,
|
||||||
|
$Res Function(_$NotTeamImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of AnalyticFailure
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$NotTeamImpl implements _NotTeam {
|
||||||
|
const _$NotTeamImpl();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AnalyticFailure.notTeam()';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType && other is _$NotTeamImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(ApiFailure failure) serverError,
|
||||||
|
required TResult Function() unexpectedError,
|
||||||
|
required TResult Function() empty,
|
||||||
|
required TResult Function() notTeam,
|
||||||
|
required TResult Function(String erroMessage) dynamicErrorMessage,
|
||||||
|
}) {
|
||||||
|
return notTeam();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(ApiFailure failure)? serverError,
|
||||||
|
TResult? Function()? unexpectedError,
|
||||||
|
TResult? Function()? empty,
|
||||||
|
TResult? Function()? notTeam,
|
||||||
|
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
||||||
|
}) {
|
||||||
|
return notTeam?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(ApiFailure failure)? serverError,
|
||||||
|
TResult Function()? unexpectedError,
|
||||||
|
TResult Function()? empty,
|
||||||
|
TResult Function()? notTeam,
|
||||||
|
TResult Function(String erroMessage)? dynamicErrorMessage,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (notTeam != null) {
|
||||||
|
return notTeam();
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_ServerError value) serverError,
|
||||||
|
required TResult Function(_UnexpectedError value) unexpectedError,
|
||||||
|
required TResult Function(_Empty value) empty,
|
||||||
|
required TResult Function(_NotTeam value) notTeam,
|
||||||
|
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
||||||
|
}) {
|
||||||
|
return notTeam(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_ServerError value)? serverError,
|
||||||
|
TResult? Function(_UnexpectedError value)? unexpectedError,
|
||||||
|
TResult? Function(_Empty value)? empty,
|
||||||
|
TResult? Function(_NotTeam value)? notTeam,
|
||||||
|
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
|
}) {
|
||||||
|
return notTeam?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_ServerError value)? serverError,
|
||||||
|
TResult Function(_UnexpectedError value)? unexpectedError,
|
||||||
|
TResult Function(_Empty value)? empty,
|
||||||
|
TResult Function(_NotTeam value)? notTeam,
|
||||||
|
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (notTeam != null) {
|
||||||
|
return notTeam(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _NotTeam implements AnalyticFailure {
|
||||||
|
const factory _NotTeam() = _$NotTeamImpl;
|
||||||
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract class _$$DynamicErrorMessageImplCopyWith<$Res> {
|
abstract class _$$DynamicErrorMessageImplCopyWith<$Res> {
|
||||||
factory _$$DynamicErrorMessageImplCopyWith(
|
factory _$$DynamicErrorMessageImplCopyWith(
|
||||||
@@ -15594,6 +15696,7 @@ class _$DynamicErrorMessageImpl implements _DynamicErrorMessage {
|
|||||||
required TResult Function(ApiFailure failure) serverError,
|
required TResult Function(ApiFailure failure) serverError,
|
||||||
required TResult Function() unexpectedError,
|
required TResult Function() unexpectedError,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
|
required TResult Function() notTeam,
|
||||||
required TResult Function(String erroMessage) dynamicErrorMessage,
|
required TResult Function(String erroMessage) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return dynamicErrorMessage(erroMessage);
|
return dynamicErrorMessage(erroMessage);
|
||||||
@@ -15605,6 +15708,7 @@ class _$DynamicErrorMessageImpl implements _DynamicErrorMessage {
|
|||||||
TResult? Function(ApiFailure failure)? serverError,
|
TResult? Function(ApiFailure failure)? serverError,
|
||||||
TResult? Function()? unexpectedError,
|
TResult? Function()? unexpectedError,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
|
TResult? Function()? notTeam,
|
||||||
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
TResult? Function(String erroMessage)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return dynamicErrorMessage?.call(erroMessage);
|
return dynamicErrorMessage?.call(erroMessage);
|
||||||
@@ -15616,6 +15720,7 @@ class _$DynamicErrorMessageImpl implements _DynamicErrorMessage {
|
|||||||
TResult Function(ApiFailure failure)? serverError,
|
TResult Function(ApiFailure failure)? serverError,
|
||||||
TResult Function()? unexpectedError,
|
TResult Function()? unexpectedError,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
|
TResult Function()? notTeam,
|
||||||
TResult Function(String erroMessage)? dynamicErrorMessage,
|
TResult Function(String erroMessage)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -15631,6 +15736,7 @@ class _$DynamicErrorMessageImpl implements _DynamicErrorMessage {
|
|||||||
required TResult Function(_ServerError value) serverError,
|
required TResult Function(_ServerError value) serverError,
|
||||||
required TResult Function(_UnexpectedError value) unexpectedError,
|
required TResult Function(_UnexpectedError value) unexpectedError,
|
||||||
required TResult Function(_Empty value) empty,
|
required TResult Function(_Empty value) empty,
|
||||||
|
required TResult Function(_NotTeam value) notTeam,
|
||||||
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return dynamicErrorMessage(this);
|
return dynamicErrorMessage(this);
|
||||||
@@ -15642,6 +15748,7 @@ class _$DynamicErrorMessageImpl implements _DynamicErrorMessage {
|
|||||||
TResult? Function(_ServerError value)? serverError,
|
TResult? Function(_ServerError value)? serverError,
|
||||||
TResult? Function(_UnexpectedError value)? unexpectedError,
|
TResult? Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult? Function(_Empty value)? empty,
|
TResult? Function(_Empty value)? empty,
|
||||||
|
TResult? Function(_NotTeam value)? notTeam,
|
||||||
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return dynamicErrorMessage?.call(this);
|
return dynamicErrorMessage?.call(this);
|
||||||
@@ -15653,6 +15760,7 @@ class _$DynamicErrorMessageImpl implements _DynamicErrorMessage {
|
|||||||
TResult Function(_ServerError value)? serverError,
|
TResult Function(_ServerError value)? serverError,
|
||||||
TResult Function(_UnexpectedError value)? unexpectedError,
|
TResult Function(_UnexpectedError value)? unexpectedError,
|
||||||
TResult Function(_Empty value)? empty,
|
TResult Function(_Empty value)? empty,
|
||||||
|
TResult Function(_NotTeam value)? notTeam,
|
||||||
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ class ProfitSharingCategory with _$ProfitSharingCategory {
|
|||||||
|
|
||||||
bool get hasTopProduct => topProduct.productId.isNotEmpty;
|
bool get hasTopProduct => topProduct.productId.isNotEmpty;
|
||||||
|
|
||||||
|
/// Porsi tim = omzet − SDL. Response tidak membawa porsi tim per kategori,
|
||||||
|
/// jadi dihitung dari nominalnya (docs/migrasi-profit-sharing.md).
|
||||||
|
int get teamShare => totalRevenue - sdl;
|
||||||
|
|
||||||
|
/// % porsi tim terhadap omzet, yaitu 100 − fee owner.
|
||||||
|
double get teamPercent => 100 - ownerFeePercent;
|
||||||
|
|
||||||
/// Laba kotor memakai HPP standar (acuan yang dipakai di laporan laba rugi).
|
/// Laba kotor memakai HPP standar (acuan yang dipakai di laporan laba rugi).
|
||||||
int get grossProfit => totalRevenue - totalStandardHpp;
|
int get grossProfit => totalRevenue - totalStandardHpp;
|
||||||
|
|
||||||
@@ -106,16 +113,16 @@ class ProfitSharingBudget with _$ProfitSharingBudget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Porsi bawaan bagi hasil: owner (SDL) dan tim, dengan tim = 100 − owner.
|
||||||
@freezed
|
@freezed
|
||||||
class ProfitSharingPercentage with _$ProfitSharingPercentage {
|
class ProfitSharingPercentage with _$ProfitSharingPercentage {
|
||||||
const factory ProfitSharingPercentage({
|
const factory ProfitSharingPercentage({
|
||||||
required double purchase,
|
|
||||||
required double owner,
|
required double owner,
|
||||||
required double team,
|
required double team,
|
||||||
}) = _ProfitSharingPercentage;
|
}) = _ProfitSharingPercentage;
|
||||||
|
|
||||||
factory ProfitSharingPercentage.empty() =>
|
factory ProfitSharingPercentage.empty() =>
|
||||||
const ProfitSharingPercentage(purchase: 0, owner: 0, team: 0);
|
const ProfitSharingPercentage(owner: 0, team: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Satu baris periode bagi hasil. Dipakai untuk total, mingguan, dan bulanan.
|
/// Satu baris periode bagi hasil. Dipakai untuk total, mingguan, dan bulanan.
|
||||||
@@ -129,7 +136,6 @@ class ProfitSharingPeriod with _$ProfitSharingPeriod {
|
|||||||
required DateTime periodEnd,
|
required DateTime periodEnd,
|
||||||
required int revenue,
|
required int revenue,
|
||||||
required int orderCount,
|
required int orderCount,
|
||||||
required int limitPurchase,
|
|
||||||
required int sdl,
|
required int sdl,
|
||||||
required int limitTeam,
|
required int limitTeam,
|
||||||
@Default('') String month,
|
@Default('') String month,
|
||||||
@@ -141,7 +147,6 @@ class ProfitSharingPeriod with _$ProfitSharingPeriod {
|
|||||||
periodEnd: DateTime.fromMillisecondsSinceEpoch(0),
|
periodEnd: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
revenue: 0,
|
revenue: 0,
|
||||||
orderCount: 0,
|
orderCount: 0,
|
||||||
limitPurchase: 0,
|
|
||||||
sdl: 0,
|
sdl: 0,
|
||||||
limitTeam: 0,
|
limitTeam: 0,
|
||||||
);
|
);
|
||||||
@@ -152,6 +157,9 @@ class ProfitSharingPeriod with _$ProfitSharingPeriod {
|
|||||||
/// induk, jadi porsinya dihitung dari nominal, bukan dari persentase tetap.
|
/// induk, jadi porsinya dihitung dari nominal, bukan dari persentase tetap.
|
||||||
double get sdlPercentage => revenue == 0 ? 0 : (sdl / revenue) * 100;
|
double get sdlPercentage => revenue == 0 ? 0 : (sdl / revenue) * 100;
|
||||||
|
|
||||||
|
/// % porsi tim terhadap omzet, dihitung dari nominal dengan alasan yang sama.
|
||||||
|
double get teamPercentage => revenue == 0 ? 0 : (limitTeam / revenue) * 100;
|
||||||
|
|
||||||
int get averageOrderValue => orderCount == 0 ? 0 : revenue ~/ orderCount;
|
int get averageOrderValue => orderCount == 0 ? 0 : revenue ~/ orderCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ sealed class AnalyticFailure with _$AnalyticFailure {
|
|||||||
const factory AnalyticFailure.serverError(ApiFailure failure) = _ServerError;
|
const factory AnalyticFailure.serverError(ApiFailure failure) = _ServerError;
|
||||||
const factory AnalyticFailure.unexpectedError() = _UnexpectedError;
|
const factory AnalyticFailure.unexpectedError() = _UnexpectedError;
|
||||||
const factory AnalyticFailure.empty() = _Empty;
|
const factory AnalyticFailure.empty() = _Empty;
|
||||||
|
|
||||||
|
/// Detail profit sharing ditolak karena kategori induknya sudah non-team.
|
||||||
|
const factory AnalyticFailure.notTeam() = _NotTeam;
|
||||||
const factory AnalyticFailure.dynamicErrorMessage(String erroMessage) =
|
const factory AnalyticFailure.dynamicErrorMessage(String erroMessage) =
|
||||||
_DynamicErrorMessage;
|
_DynamicErrorMessage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15656,8 +15656,6 @@ ProfitSharingPercentageDto _$ProfitSharingPercentageDtoFromJson(
|
|||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$ProfitSharingPercentageDto {
|
mixin _$ProfitSharingPercentageDto {
|
||||||
@JsonKey(name: 'purchase')
|
|
||||||
num? get purchase => throw _privateConstructorUsedError;
|
|
||||||
@JsonKey(name: 'owner')
|
@JsonKey(name: 'owner')
|
||||||
num? get owner => throw _privateConstructorUsedError;
|
num? get owner => throw _privateConstructorUsedError;
|
||||||
@JsonKey(name: 'team')
|
@JsonKey(name: 'team')
|
||||||
@@ -15685,7 +15683,6 @@ abstract class $ProfitSharingPercentageDtoCopyWith<$Res> {
|
|||||||
>;
|
>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
@JsonKey(name: 'purchase') num? purchase,
|
|
||||||
@JsonKey(name: 'owner') num? owner,
|
@JsonKey(name: 'owner') num? owner,
|
||||||
@JsonKey(name: 'team') num? team,
|
@JsonKey(name: 'team') num? team,
|
||||||
});
|
});
|
||||||
@@ -15708,17 +15705,9 @@ class _$ProfitSharingPercentageDtoCopyWithImpl<
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({Object? owner = freezed, Object? team = freezed}) {
|
||||||
Object? purchase = freezed,
|
|
||||||
Object? owner = freezed,
|
|
||||||
Object? team = freezed,
|
|
||||||
}) {
|
|
||||||
return _then(
|
return _then(
|
||||||
_value.copyWith(
|
_value.copyWith(
|
||||||
purchase: freezed == purchase
|
|
||||||
? _value.purchase
|
|
||||||
: purchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as num?,
|
|
||||||
owner: freezed == owner
|
owner: freezed == owner
|
||||||
? _value.owner
|
? _value.owner
|
||||||
: owner // ignore: cast_nullable_to_non_nullable
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -15743,7 +15732,6 @@ abstract class _$$ProfitSharingPercentageDtoImplCopyWith<$Res>
|
|||||||
@override
|
@override
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
@JsonKey(name: 'purchase') num? purchase,
|
|
||||||
@JsonKey(name: 'owner') num? owner,
|
@JsonKey(name: 'owner') num? owner,
|
||||||
@JsonKey(name: 'team') num? team,
|
@JsonKey(name: 'team') num? team,
|
||||||
});
|
});
|
||||||
@@ -15766,17 +15754,9 @@ class __$$ProfitSharingPercentageDtoImplCopyWithImpl<$Res>
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({Object? owner = freezed, Object? team = freezed}) {
|
||||||
Object? purchase = freezed,
|
|
||||||
Object? owner = freezed,
|
|
||||||
Object? team = freezed,
|
|
||||||
}) {
|
|
||||||
return _then(
|
return _then(
|
||||||
_$ProfitSharingPercentageDtoImpl(
|
_$ProfitSharingPercentageDtoImpl(
|
||||||
purchase: freezed == purchase
|
|
||||||
? _value.purchase
|
|
||||||
: purchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as num?,
|
|
||||||
owner: freezed == owner
|
owner: freezed == owner
|
||||||
? _value.owner
|
? _value.owner
|
||||||
: owner // ignore: cast_nullable_to_non_nullable
|
: owner // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -15794,7 +15774,6 @@ class __$$ProfitSharingPercentageDtoImplCopyWithImpl<$Res>
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$ProfitSharingPercentageDtoImpl extends _ProfitSharingPercentageDto {
|
class _$ProfitSharingPercentageDtoImpl extends _ProfitSharingPercentageDto {
|
||||||
const _$ProfitSharingPercentageDtoImpl({
|
const _$ProfitSharingPercentageDtoImpl({
|
||||||
@JsonKey(name: 'purchase') this.purchase,
|
|
||||||
@JsonKey(name: 'owner') this.owner,
|
@JsonKey(name: 'owner') this.owner,
|
||||||
@JsonKey(name: 'team') this.team,
|
@JsonKey(name: 'team') this.team,
|
||||||
}) : super._();
|
}) : super._();
|
||||||
@@ -15803,9 +15782,6 @@ class _$ProfitSharingPercentageDtoImpl extends _ProfitSharingPercentageDto {
|
|||||||
Map<String, dynamic> json,
|
Map<String, dynamic> json,
|
||||||
) => _$$ProfitSharingPercentageDtoImplFromJson(json);
|
) => _$$ProfitSharingPercentageDtoImplFromJson(json);
|
||||||
|
|
||||||
@override
|
|
||||||
@JsonKey(name: 'purchase')
|
|
||||||
final num? purchase;
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(name: 'owner')
|
@JsonKey(name: 'owner')
|
||||||
final num? owner;
|
final num? owner;
|
||||||
@@ -15815,7 +15791,7 @@ class _$ProfitSharingPercentageDtoImpl extends _ProfitSharingPercentageDto {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ProfitSharingPercentageDto(purchase: $purchase, owner: $owner, team: $team)';
|
return 'ProfitSharingPercentageDto(owner: $owner, team: $team)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -15823,15 +15799,13 @@ class _$ProfitSharingPercentageDtoImpl extends _ProfitSharingPercentageDto {
|
|||||||
return identical(this, other) ||
|
return identical(this, other) ||
|
||||||
(other.runtimeType == runtimeType &&
|
(other.runtimeType == runtimeType &&
|
||||||
other is _$ProfitSharingPercentageDtoImpl &&
|
other is _$ProfitSharingPercentageDtoImpl &&
|
||||||
(identical(other.purchase, purchase) ||
|
|
||||||
other.purchase == purchase) &&
|
|
||||||
(identical(other.owner, owner) || other.owner == owner) &&
|
(identical(other.owner, owner) || other.owner == owner) &&
|
||||||
(identical(other.team, team) || other.team == team));
|
(identical(other.team, team) || other.team == team));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, purchase, owner, team);
|
int get hashCode => Object.hash(runtimeType, owner, team);
|
||||||
|
|
||||||
/// Create a copy of ProfitSharingPercentageDto
|
/// Create a copy of ProfitSharingPercentageDto
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -15852,7 +15826,6 @@ class _$ProfitSharingPercentageDtoImpl extends _ProfitSharingPercentageDto {
|
|||||||
|
|
||||||
abstract class _ProfitSharingPercentageDto extends ProfitSharingPercentageDto {
|
abstract class _ProfitSharingPercentageDto extends ProfitSharingPercentageDto {
|
||||||
const factory _ProfitSharingPercentageDto({
|
const factory _ProfitSharingPercentageDto({
|
||||||
@JsonKey(name: 'purchase') final num? purchase,
|
|
||||||
@JsonKey(name: 'owner') final num? owner,
|
@JsonKey(name: 'owner') final num? owner,
|
||||||
@JsonKey(name: 'team') final num? team,
|
@JsonKey(name: 'team') final num? team,
|
||||||
}) = _$ProfitSharingPercentageDtoImpl;
|
}) = _$ProfitSharingPercentageDtoImpl;
|
||||||
@@ -15861,9 +15834,6 @@ abstract class _ProfitSharingPercentageDto extends ProfitSharingPercentageDto {
|
|||||||
factory _ProfitSharingPercentageDto.fromJson(Map<String, dynamic> json) =
|
factory _ProfitSharingPercentageDto.fromJson(Map<String, dynamic> json) =
|
||||||
_$ProfitSharingPercentageDtoImpl.fromJson;
|
_$ProfitSharingPercentageDtoImpl.fromJson;
|
||||||
|
|
||||||
@override
|
|
||||||
@JsonKey(name: 'purchase')
|
|
||||||
num? get purchase;
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(name: 'owner')
|
@JsonKey(name: 'owner')
|
||||||
num? get owner;
|
num? get owner;
|
||||||
@@ -15895,8 +15865,6 @@ mixin _$ProfitSharingPeriodDto {
|
|||||||
num? get revenue => throw _privateConstructorUsedError;
|
num? get revenue => throw _privateConstructorUsedError;
|
||||||
@JsonKey(name: 'order_count')
|
@JsonKey(name: 'order_count')
|
||||||
num? get orderCount => throw _privateConstructorUsedError;
|
num? get orderCount => throw _privateConstructorUsedError;
|
||||||
@JsonKey(name: 'limit_purchase')
|
|
||||||
num? get limitPurchase => throw _privateConstructorUsedError;
|
|
||||||
@JsonKey(name: 'sdl')
|
@JsonKey(name: 'sdl')
|
||||||
num? get sdl => throw _privateConstructorUsedError;
|
num? get sdl => throw _privateConstructorUsedError;
|
||||||
@JsonKey(name: 'limit_team')
|
@JsonKey(name: 'limit_team')
|
||||||
@@ -15928,7 +15896,6 @@ abstract class $ProfitSharingPeriodDtoCopyWith<$Res> {
|
|||||||
@JsonKey(name: 'period_end') DateTime? periodEnd,
|
@JsonKey(name: 'period_end') DateTime? periodEnd,
|
||||||
@JsonKey(name: 'revenue') num? revenue,
|
@JsonKey(name: 'revenue') num? revenue,
|
||||||
@JsonKey(name: 'order_count') num? orderCount,
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
@JsonKey(name: 'limit_purchase') num? limitPurchase,
|
|
||||||
@JsonKey(name: 'sdl') num? sdl,
|
@JsonKey(name: 'sdl') num? sdl,
|
||||||
@JsonKey(name: 'limit_team') num? limitTeam,
|
@JsonKey(name: 'limit_team') num? limitTeam,
|
||||||
@JsonKey(name: 'month') String? month,
|
@JsonKey(name: 'month') String? month,
|
||||||
@@ -15958,7 +15925,6 @@ class _$ProfitSharingPeriodDtoCopyWithImpl<
|
|||||||
Object? periodEnd = freezed,
|
Object? periodEnd = freezed,
|
||||||
Object? revenue = freezed,
|
Object? revenue = freezed,
|
||||||
Object? orderCount = freezed,
|
Object? orderCount = freezed,
|
||||||
Object? limitPurchase = freezed,
|
|
||||||
Object? sdl = freezed,
|
Object? sdl = freezed,
|
||||||
Object? limitTeam = freezed,
|
Object? limitTeam = freezed,
|
||||||
Object? month = freezed,
|
Object? month = freezed,
|
||||||
@@ -15982,10 +15948,6 @@ class _$ProfitSharingPeriodDtoCopyWithImpl<
|
|||||||
? _value.orderCount
|
? _value.orderCount
|
||||||
: orderCount // ignore: cast_nullable_to_non_nullable
|
: orderCount // ignore: cast_nullable_to_non_nullable
|
||||||
as num?,
|
as num?,
|
||||||
limitPurchase: freezed == limitPurchase
|
|
||||||
? _value.limitPurchase
|
|
||||||
: limitPurchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as num?,
|
|
||||||
sdl: freezed == sdl
|
sdl: freezed == sdl
|
||||||
? _value.sdl
|
? _value.sdl
|
||||||
: sdl // ignore: cast_nullable_to_non_nullable
|
: sdl // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -16022,7 +15984,6 @@ abstract class _$$ProfitSharingPeriodDtoImplCopyWith<$Res>
|
|||||||
@JsonKey(name: 'period_end') DateTime? periodEnd,
|
@JsonKey(name: 'period_end') DateTime? periodEnd,
|
||||||
@JsonKey(name: 'revenue') num? revenue,
|
@JsonKey(name: 'revenue') num? revenue,
|
||||||
@JsonKey(name: 'order_count') num? orderCount,
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
@JsonKey(name: 'limit_purchase') num? limitPurchase,
|
|
||||||
@JsonKey(name: 'sdl') num? sdl,
|
@JsonKey(name: 'sdl') num? sdl,
|
||||||
@JsonKey(name: 'limit_team') num? limitTeam,
|
@JsonKey(name: 'limit_team') num? limitTeam,
|
||||||
@JsonKey(name: 'month') String? month,
|
@JsonKey(name: 'month') String? month,
|
||||||
@@ -16049,7 +16010,6 @@ class __$$ProfitSharingPeriodDtoImplCopyWithImpl<$Res>
|
|||||||
Object? periodEnd = freezed,
|
Object? periodEnd = freezed,
|
||||||
Object? revenue = freezed,
|
Object? revenue = freezed,
|
||||||
Object? orderCount = freezed,
|
Object? orderCount = freezed,
|
||||||
Object? limitPurchase = freezed,
|
|
||||||
Object? sdl = freezed,
|
Object? sdl = freezed,
|
||||||
Object? limitTeam = freezed,
|
Object? limitTeam = freezed,
|
||||||
Object? month = freezed,
|
Object? month = freezed,
|
||||||
@@ -16073,10 +16033,6 @@ class __$$ProfitSharingPeriodDtoImplCopyWithImpl<$Res>
|
|||||||
? _value.orderCount
|
? _value.orderCount
|
||||||
: orderCount // ignore: cast_nullable_to_non_nullable
|
: orderCount // ignore: cast_nullable_to_non_nullable
|
||||||
as num?,
|
as num?,
|
||||||
limitPurchase: freezed == limitPurchase
|
|
||||||
? _value.limitPurchase
|
|
||||||
: limitPurchase // ignore: cast_nullable_to_non_nullable
|
|
||||||
as num?,
|
|
||||||
sdl: freezed == sdl
|
sdl: freezed == sdl
|
||||||
? _value.sdl
|
? _value.sdl
|
||||||
: sdl // ignore: cast_nullable_to_non_nullable
|
: sdl // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -16106,7 +16062,6 @@ class _$ProfitSharingPeriodDtoImpl extends _ProfitSharingPeriodDto {
|
|||||||
@JsonKey(name: 'period_end') this.periodEnd,
|
@JsonKey(name: 'period_end') this.periodEnd,
|
||||||
@JsonKey(name: 'revenue') this.revenue,
|
@JsonKey(name: 'revenue') this.revenue,
|
||||||
@JsonKey(name: 'order_count') this.orderCount,
|
@JsonKey(name: 'order_count') this.orderCount,
|
||||||
@JsonKey(name: 'limit_purchase') this.limitPurchase,
|
|
||||||
@JsonKey(name: 'sdl') this.sdl,
|
@JsonKey(name: 'sdl') this.sdl,
|
||||||
@JsonKey(name: 'limit_team') this.limitTeam,
|
@JsonKey(name: 'limit_team') this.limitTeam,
|
||||||
@JsonKey(name: 'month') this.month,
|
@JsonKey(name: 'month') this.month,
|
||||||
@@ -16129,9 +16084,6 @@ class _$ProfitSharingPeriodDtoImpl extends _ProfitSharingPeriodDto {
|
|||||||
@JsonKey(name: 'order_count')
|
@JsonKey(name: 'order_count')
|
||||||
final num? orderCount;
|
final num? orderCount;
|
||||||
@override
|
@override
|
||||||
@JsonKey(name: 'limit_purchase')
|
|
||||||
final num? limitPurchase;
|
|
||||||
@override
|
|
||||||
@JsonKey(name: 'sdl')
|
@JsonKey(name: 'sdl')
|
||||||
final num? sdl;
|
final num? sdl;
|
||||||
@override
|
@override
|
||||||
@@ -16146,7 +16098,7 @@ class _$ProfitSharingPeriodDtoImpl extends _ProfitSharingPeriodDto {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ProfitSharingPeriodDto(periodStart: $periodStart, periodEnd: $periodEnd, revenue: $revenue, orderCount: $orderCount, limitPurchase: $limitPurchase, sdl: $sdl, limitTeam: $limitTeam, month: $month, weekCount: $weekCount)';
|
return 'ProfitSharingPeriodDto(periodStart: $periodStart, periodEnd: $periodEnd, revenue: $revenue, orderCount: $orderCount, sdl: $sdl, limitTeam: $limitTeam, month: $month, weekCount: $weekCount)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -16161,8 +16113,6 @@ class _$ProfitSharingPeriodDtoImpl extends _ProfitSharingPeriodDto {
|
|||||||
(identical(other.revenue, revenue) || other.revenue == revenue) &&
|
(identical(other.revenue, revenue) || other.revenue == revenue) &&
|
||||||
(identical(other.orderCount, orderCount) ||
|
(identical(other.orderCount, orderCount) ||
|
||||||
other.orderCount == orderCount) &&
|
other.orderCount == orderCount) &&
|
||||||
(identical(other.limitPurchase, limitPurchase) ||
|
|
||||||
other.limitPurchase == limitPurchase) &&
|
|
||||||
(identical(other.sdl, sdl) || other.sdl == sdl) &&
|
(identical(other.sdl, sdl) || other.sdl == sdl) &&
|
||||||
(identical(other.limitTeam, limitTeam) ||
|
(identical(other.limitTeam, limitTeam) ||
|
||||||
other.limitTeam == limitTeam) &&
|
other.limitTeam == limitTeam) &&
|
||||||
@@ -16179,7 +16129,6 @@ class _$ProfitSharingPeriodDtoImpl extends _ProfitSharingPeriodDto {
|
|||||||
periodEnd,
|
periodEnd,
|
||||||
revenue,
|
revenue,
|
||||||
orderCount,
|
orderCount,
|
||||||
limitPurchase,
|
|
||||||
sdl,
|
sdl,
|
||||||
limitTeam,
|
limitTeam,
|
||||||
month,
|
month,
|
||||||
@@ -16210,7 +16159,6 @@ abstract class _ProfitSharingPeriodDto extends ProfitSharingPeriodDto {
|
|||||||
@JsonKey(name: 'period_end') final DateTime? periodEnd,
|
@JsonKey(name: 'period_end') final DateTime? periodEnd,
|
||||||
@JsonKey(name: 'revenue') final num? revenue,
|
@JsonKey(name: 'revenue') final num? revenue,
|
||||||
@JsonKey(name: 'order_count') final num? orderCount,
|
@JsonKey(name: 'order_count') final num? orderCount,
|
||||||
@JsonKey(name: 'limit_purchase') final num? limitPurchase,
|
|
||||||
@JsonKey(name: 'sdl') final num? sdl,
|
@JsonKey(name: 'sdl') final num? sdl,
|
||||||
@JsonKey(name: 'limit_team') final num? limitTeam,
|
@JsonKey(name: 'limit_team') final num? limitTeam,
|
||||||
@JsonKey(name: 'month') final String? month,
|
@JsonKey(name: 'month') final String? month,
|
||||||
@@ -16234,9 +16182,6 @@ abstract class _ProfitSharingPeriodDto extends ProfitSharingPeriodDto {
|
|||||||
@JsonKey(name: 'order_count')
|
@JsonKey(name: 'order_count')
|
||||||
num? get orderCount;
|
num? get orderCount;
|
||||||
@override
|
@override
|
||||||
@JsonKey(name: 'limit_purchase')
|
|
||||||
num? get limitPurchase;
|
|
||||||
@override
|
|
||||||
@JsonKey(name: 'sdl')
|
@JsonKey(name: 'sdl')
|
||||||
num? get sdl;
|
num? get sdl;
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1251,18 +1251,13 @@ Map<String, dynamic> _$$ProfitSharingBudgetDtoImplToJson(
|
|||||||
_$ProfitSharingPercentageDtoImpl _$$ProfitSharingPercentageDtoImplFromJson(
|
_$ProfitSharingPercentageDtoImpl _$$ProfitSharingPercentageDtoImplFromJson(
|
||||||
Map<String, dynamic> json,
|
Map<String, dynamic> json,
|
||||||
) => _$ProfitSharingPercentageDtoImpl(
|
) => _$ProfitSharingPercentageDtoImpl(
|
||||||
purchase: json['purchase'] as num?,
|
|
||||||
owner: json['owner'] as num?,
|
owner: json['owner'] as num?,
|
||||||
team: json['team'] as num?,
|
team: json['team'] as num?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$ProfitSharingPercentageDtoImplToJson(
|
Map<String, dynamic> _$$ProfitSharingPercentageDtoImplToJson(
|
||||||
_$ProfitSharingPercentageDtoImpl instance,
|
_$ProfitSharingPercentageDtoImpl instance,
|
||||||
) => <String, dynamic>{
|
) => <String, dynamic>{'owner': instance.owner, 'team': instance.team};
|
||||||
'purchase': instance.purchase,
|
|
||||||
'owner': instance.owner,
|
|
||||||
'team': instance.team,
|
|
||||||
};
|
|
||||||
|
|
||||||
_$ProfitSharingPeriodDtoImpl _$$ProfitSharingPeriodDtoImplFromJson(
|
_$ProfitSharingPeriodDtoImpl _$$ProfitSharingPeriodDtoImplFromJson(
|
||||||
Map<String, dynamic> json,
|
Map<String, dynamic> json,
|
||||||
@@ -1275,7 +1270,6 @@ _$ProfitSharingPeriodDtoImpl _$$ProfitSharingPeriodDtoImplFromJson(
|
|||||||
: DateTime.parse(json['period_end'] as String),
|
: DateTime.parse(json['period_end'] as String),
|
||||||
revenue: json['revenue'] as num?,
|
revenue: json['revenue'] as num?,
|
||||||
orderCount: json['order_count'] as num?,
|
orderCount: json['order_count'] as num?,
|
||||||
limitPurchase: json['limit_purchase'] as num?,
|
|
||||||
sdl: json['sdl'] as num?,
|
sdl: json['sdl'] as num?,
|
||||||
limitTeam: json['limit_team'] as num?,
|
limitTeam: json['limit_team'] as num?,
|
||||||
month: json['month'] as String?,
|
month: json['month'] as String?,
|
||||||
@@ -1289,7 +1283,6 @@ Map<String, dynamic> _$$ProfitSharingPeriodDtoImplToJson(
|
|||||||
'period_end': instance.periodEnd?.toIso8601String(),
|
'period_end': instance.periodEnd?.toIso8601String(),
|
||||||
'revenue': instance.revenue,
|
'revenue': instance.revenue,
|
||||||
'order_count': instance.orderCount,
|
'order_count': instance.orderCount,
|
||||||
'limit_purchase': instance.limitPurchase,
|
|
||||||
'sdl': instance.sdl,
|
'sdl': instance.sdl,
|
||||||
'limit_team': instance.limitTeam,
|
'limit_team': instance.limitTeam,
|
||||||
'month': instance.month,
|
'month': instance.month,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:data_channel/data_channel.dart';
|
import 'package:data_channel/data_channel.dart';
|
||||||
|
import 'package:dio/dio.dart' show Response;
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
import '../../../common/api/api_client.dart';
|
import '../../../common/api/api_client.dart';
|
||||||
@@ -291,7 +292,12 @@ class AnalyticRemoteDataProvider {
|
|||||||
|
|
||||||
return DC.data(dto);
|
return DC.data(dto);
|
||||||
} on ApiFailure catch (e, s) {
|
} on ApiFailure catch (e, s) {
|
||||||
log('fetchExclusiveSummaryError', name: _logName, error: e, stackTrace: s);
|
log(
|
||||||
|
'fetchExclusiveSummaryError',
|
||||||
|
name: _logName,
|
||||||
|
error: e,
|
||||||
|
stackTrace: s,
|
||||||
|
);
|
||||||
return DC.error(AnalyticFailure.serverError(e));
|
return DC.error(AnalyticFailure.serverError(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,17 +316,18 @@ class AnalyticRemoteDataProvider {
|
|||||||
};
|
};
|
||||||
if (outletId != null) params['outlet_id'] = outletId;
|
if (outletId != null) params['outlet_id'] = outletId;
|
||||||
|
|
||||||
final response = await _apiClient.get(
|
final response = await _getProfitSharing('', params);
|
||||||
ApiPath.parentCategoryAnalytic,
|
|
||||||
params: params,
|
|
||||||
headers: getAuthorizationHeader(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.data['data'] == null) {
|
final failure = _profitSharingFailure(response);
|
||||||
|
if (failure != null) return DC.error(failure);
|
||||||
|
|
||||||
|
final body = response.data;
|
||||||
|
final data = body is Map ? body['data'] : null;
|
||||||
|
if (data == null) {
|
||||||
return DC.error(AnalyticFailure.empty());
|
return DC.error(AnalyticFailure.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
final dto = ProfitSharingDto.fromJson(response.data['data']);
|
final dto = ProfitSharingDto.fromJson(data);
|
||||||
|
|
||||||
return DC.data(dto);
|
return DC.data(dto);
|
||||||
} on ApiFailure catch (e, s) {
|
} on ApiFailure catch (e, s) {
|
||||||
@@ -342,17 +349,18 @@ class AnalyticRemoteDataProvider {
|
|||||||
};
|
};
|
||||||
if (outletId != null) params['outlet_id'] = outletId;
|
if (outletId != null) params['outlet_id'] = outletId;
|
||||||
|
|
||||||
final response = await _apiClient.get(
|
final response = await _getProfitSharing('/$parentCategoryId', params);
|
||||||
'${ApiPath.parentCategoryAnalytic}/$parentCategoryId',
|
|
||||||
params: params,
|
|
||||||
headers: getAuthorizationHeader(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.data['data'] == null) {
|
final failure = _profitSharingFailure(response);
|
||||||
|
if (failure != null) return DC.error(failure);
|
||||||
|
|
||||||
|
final body = response.data;
|
||||||
|
final data = body is Map ? body['data'] : null;
|
||||||
|
if (data == null) {
|
||||||
return DC.error(AnalyticFailure.empty());
|
return DC.error(AnalyticFailure.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
final dto = ProfitSharingDetailDto.fromJson(response.data['data']);
|
final dto = ProfitSharingDetailDto.fromJson(data);
|
||||||
|
|
||||||
return DC.data(dto);
|
return DC.data(dto);
|
||||||
} on ApiFailure catch (e, s) {
|
} on ApiFailure catch (e, s) {
|
||||||
@@ -365,4 +373,43 @@ class AnalyticRemoteDataProvider {
|
|||||||
return DC.error(AnalyticFailure.serverError(e));
|
return DC.error(AnalyticFailure.serverError(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// GET ke endpoint profit sharing. Selama backend lama masih jalan path baru
|
||||||
|
/// mengembalikan 404, jadi dicoba sekali lagi ke path lama.
|
||||||
|
Future<Response> _getProfitSharing(
|
||||||
|
String subPath,
|
||||||
|
Map<String, dynamic> params,
|
||||||
|
) async {
|
||||||
|
Future<Response> request(String basePath) => _apiClient.get(
|
||||||
|
'$basePath$subPath',
|
||||||
|
params: params,
|
||||||
|
headers: getAuthorizationHeader(),
|
||||||
|
// Status 5xx tidak dilempar supaya `cause` di body masih bisa dibaca.
|
||||||
|
validateStatus: (status) => status != null && status < 600,
|
||||||
|
);
|
||||||
|
|
||||||
|
final response = await request(ApiPath.profitSharingAnalytic);
|
||||||
|
if (response.statusCode != 404) return response;
|
||||||
|
return request(ApiPath.profitSharingAnalyticLegacy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Failure dari status error endpoint profit sharing, null kalau berhasil.
|
||||||
|
/// Detail kategori non-team ditolak 500 dengan `cause` "... is not a team".
|
||||||
|
AnalyticFailure? _profitSharingFailure(Response response) {
|
||||||
|
final status = response.statusCode ?? 0;
|
||||||
|
if (status == 404) {
|
||||||
|
return const AnalyticFailure.serverError(ApiFailure.notFound(null));
|
||||||
|
}
|
||||||
|
if (status < 500) return null;
|
||||||
|
|
||||||
|
final body = response.data;
|
||||||
|
final errors = body is Map ? body['errors'] : null;
|
||||||
|
final isNotTeam =
|
||||||
|
errors is List &&
|
||||||
|
errors.any(
|
||||||
|
(e) => e is Map && '${e['cause']}'.contains('is not a team'),
|
||||||
|
);
|
||||||
|
if (isNotTeam) return const AnalyticFailure.notTeam();
|
||||||
|
return const AnalyticFailure.serverError(ApiFailure.internalServerError());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,6 @@ class ProfitSharingPercentageDto with _$ProfitSharingPercentageDto {
|
|||||||
const ProfitSharingPercentageDto._();
|
const ProfitSharingPercentageDto._();
|
||||||
|
|
||||||
const factory ProfitSharingPercentageDto({
|
const factory ProfitSharingPercentageDto({
|
||||||
@JsonKey(name: 'purchase') num? purchase,
|
|
||||||
@JsonKey(name: 'owner') num? owner,
|
@JsonKey(name: 'owner') num? owner,
|
||||||
@JsonKey(name: 'team') num? team,
|
@JsonKey(name: 'team') num? team,
|
||||||
}) = _ProfitSharingPercentageDto;
|
}) = _ProfitSharingPercentageDto;
|
||||||
@@ -130,7 +129,6 @@ class ProfitSharingPercentageDto with _$ProfitSharingPercentageDto {
|
|||||||
_$ProfitSharingPercentageDtoFromJson(json);
|
_$ProfitSharingPercentageDtoFromJson(json);
|
||||||
|
|
||||||
ProfitSharingPercentage toDomain() => ProfitSharingPercentage(
|
ProfitSharingPercentage toDomain() => ProfitSharingPercentage(
|
||||||
purchase: purchase?.toDouble() ?? 0,
|
|
||||||
owner: owner?.toDouble() ?? 0,
|
owner: owner?.toDouble() ?? 0,
|
||||||
team: team?.toDouble() ?? 0,
|
team: team?.toDouble() ?? 0,
|
||||||
);
|
);
|
||||||
@@ -145,7 +143,6 @@ class ProfitSharingPeriodDto with _$ProfitSharingPeriodDto {
|
|||||||
@JsonKey(name: 'period_end') DateTime? periodEnd,
|
@JsonKey(name: 'period_end') DateTime? periodEnd,
|
||||||
@JsonKey(name: 'revenue') num? revenue,
|
@JsonKey(name: 'revenue') num? revenue,
|
||||||
@JsonKey(name: 'order_count') num? orderCount,
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
@JsonKey(name: 'limit_purchase') num? limitPurchase,
|
|
||||||
@JsonKey(name: 'sdl') num? sdl,
|
@JsonKey(name: 'sdl') num? sdl,
|
||||||
@JsonKey(name: 'limit_team') num? limitTeam,
|
@JsonKey(name: 'limit_team') num? limitTeam,
|
||||||
@JsonKey(name: 'month') String? month,
|
@JsonKey(name: 'month') String? month,
|
||||||
@@ -161,7 +158,6 @@ class ProfitSharingPeriodDto with _$ProfitSharingPeriodDto {
|
|||||||
periodEnd: periodEnd?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
periodEnd: periodEnd?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
revenue: revenue?.toInt() ?? 0,
|
revenue: revenue?.toInt() ?? 0,
|
||||||
orderCount: orderCount?.toInt() ?? 0,
|
orderCount: orderCount?.toInt() ?? 0,
|
||||||
limitPurchase: limitPurchase?.toInt() ?? 0,
|
|
||||||
sdl: sdl?.toInt() ?? 0,
|
sdl: sdl?.toInt() ?? 0,
|
||||||
limitTeam: limitTeam?.toInt() ?? 0,
|
limitTeam: limitTeam?.toInt() ?? 0,
|
||||||
month: month ?? '',
|
month: month ?? '',
|
||||||
|
|||||||
+20
-3
@@ -541,18 +541,35 @@
|
|||||||
"@total_inventory_value": {},
|
"@total_inventory_value": {},
|
||||||
"profit_sharing": "Profit Sharing",
|
"profit_sharing": "Profit Sharing",
|
||||||
"@profit_sharing": {},
|
"@profit_sharing": {},
|
||||||
"profit_sharing_desc": "Revenue allocation for purchasing, owner, and team",
|
"profit_sharing_desc": "Revenue allocation for owner (SDL) and team",
|
||||||
"@profit_sharing_desc": {},
|
"@profit_sharing_desc": {},
|
||||||
"profit_sharing_allocation": "Profit Sharing Allocation",
|
"profit_sharing_allocation": "Profit Sharing Allocation",
|
||||||
"@profit_sharing_allocation": {},
|
"@profit_sharing_allocation": {},
|
||||||
"share_purchase": "Purchasing",
|
"profit_sharing_not_team": "This category is no longer part of profit sharing",
|
||||||
"@share_purchase": {},
|
"@profit_sharing_not_team": {},
|
||||||
"share_owner": "Owner",
|
"share_owner": "Owner",
|
||||||
"@share_owner": {},
|
"@share_owner": {},
|
||||||
"share_team": "Team",
|
"share_team": "Team",
|
||||||
"@share_team": {},
|
"@share_team": {},
|
||||||
"sdl": "SDL",
|
"sdl": "SDL",
|
||||||
"@sdl": {},
|
"@sdl": {},
|
||||||
|
"sdl_summary": "SDL Summary",
|
||||||
|
"@sdl_summary": {},
|
||||||
|
"sdl_desc": "Owner's share of revenue",
|
||||||
|
"@sdl_desc": {},
|
||||||
|
"sdl_per_parent_category": "SDL per Parent Category",
|
||||||
|
"@sdl_per_parent_category": {},
|
||||||
|
"sdl_per_week": "SDL per Week",
|
||||||
|
"@sdl_per_week": {},
|
||||||
|
"from_revenue": "from {revenue} revenue",
|
||||||
|
"@from_revenue": {
|
||||||
|
"placeholders": {
|
||||||
|
"revenue": {
|
||||||
|
"type": "String",
|
||||||
|
"example": "Rp 52,500,000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"top_product": "Top Product",
|
"top_product": "Top Product",
|
||||||
"@top_product": {},
|
"@top_product": {},
|
||||||
"weekly": "Weekly",
|
"weekly": "Weekly",
|
||||||
|
|||||||
+20
-3
@@ -541,18 +541,35 @@
|
|||||||
"@total_inventory_value": {},
|
"@total_inventory_value": {},
|
||||||
"profit_sharing": "Bagi Hasil",
|
"profit_sharing": "Bagi Hasil",
|
||||||
"@profit_sharing": {},
|
"@profit_sharing": {},
|
||||||
"profit_sharing_desc": "Alokasi omzet untuk belanja, owner, dan tim",
|
"profit_sharing_desc": "Alokasi omzet untuk owner (SDL) dan tim",
|
||||||
"@profit_sharing_desc": {},
|
"@profit_sharing_desc": {},
|
||||||
"profit_sharing_allocation": "Alokasi Bagi Hasil",
|
"profit_sharing_allocation": "Alokasi Bagi Hasil",
|
||||||
"@profit_sharing_allocation": {},
|
"@profit_sharing_allocation": {},
|
||||||
"share_purchase": "Belanja",
|
"profit_sharing_not_team": "Kategori ini sudah tidak ikut bagi hasil",
|
||||||
"@share_purchase": {},
|
"@profit_sharing_not_team": {},
|
||||||
"share_owner": "Owner",
|
"share_owner": "Owner",
|
||||||
"@share_owner": {},
|
"@share_owner": {},
|
||||||
"share_team": "Tim",
|
"share_team": "Tim",
|
||||||
"@share_team": {},
|
"@share_team": {},
|
||||||
"sdl": "SDL",
|
"sdl": "SDL",
|
||||||
"@sdl": {},
|
"@sdl": {},
|
||||||
|
"sdl_summary": "Ringkasan SDL",
|
||||||
|
"@sdl_summary": {},
|
||||||
|
"sdl_desc": "Bagian owner dari omzet",
|
||||||
|
"@sdl_desc": {},
|
||||||
|
"sdl_per_parent_category": "SDL per Kategori Induk",
|
||||||
|
"@sdl_per_parent_category": {},
|
||||||
|
"sdl_per_week": "SDL per Minggu",
|
||||||
|
"@sdl_per_week": {},
|
||||||
|
"from_revenue": "dari omzet {revenue}",
|
||||||
|
"@from_revenue": {
|
||||||
|
"placeholders": {
|
||||||
|
"revenue": {
|
||||||
|
"type": "String",
|
||||||
|
"example": "Rp 52.500.000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"top_product": "Produk Terlaris",
|
"top_product": "Produk Terlaris",
|
||||||
"@top_product": {},
|
"@top_product": {},
|
||||||
"weekly": "Mingguan",
|
"weekly": "Mingguan",
|
||||||
|
|||||||
@@ -1574,7 +1574,7 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @profit_sharing_desc.
|
/// No description provided for @profit_sharing_desc.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Revenue allocation for purchasing, owner, and team'**
|
/// **'Revenue allocation for owner (SDL) and team'**
|
||||||
String get profit_sharing_desc;
|
String get profit_sharing_desc;
|
||||||
|
|
||||||
/// No description provided for @profit_sharing_allocation.
|
/// No description provided for @profit_sharing_allocation.
|
||||||
@@ -1583,11 +1583,11 @@ abstract class AppLocalizations {
|
|||||||
/// **'Profit Sharing Allocation'**
|
/// **'Profit Sharing Allocation'**
|
||||||
String get profit_sharing_allocation;
|
String get profit_sharing_allocation;
|
||||||
|
|
||||||
/// No description provided for @share_purchase.
|
/// No description provided for @profit_sharing_not_team.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Purchasing'**
|
/// **'This category is no longer part of profit sharing'**
|
||||||
String get share_purchase;
|
String get profit_sharing_not_team;
|
||||||
|
|
||||||
/// No description provided for @share_owner.
|
/// No description provided for @share_owner.
|
||||||
///
|
///
|
||||||
@@ -1607,6 +1607,36 @@ abstract class AppLocalizations {
|
|||||||
/// **'SDL'**
|
/// **'SDL'**
|
||||||
String get sdl;
|
String get sdl;
|
||||||
|
|
||||||
|
/// No description provided for @sdl_summary.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'SDL Summary'**
|
||||||
|
String get sdl_summary;
|
||||||
|
|
||||||
|
/// No description provided for @sdl_desc.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Owner\'s share of revenue'**
|
||||||
|
String get sdl_desc;
|
||||||
|
|
||||||
|
/// No description provided for @sdl_per_parent_category.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'SDL per Parent Category'**
|
||||||
|
String get sdl_per_parent_category;
|
||||||
|
|
||||||
|
/// No description provided for @sdl_per_week.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'SDL per Week'**
|
||||||
|
String get sdl_per_week;
|
||||||
|
|
||||||
|
/// No description provided for @from_revenue.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'from {revenue} revenue'**
|
||||||
|
String from_revenue(String revenue);
|
||||||
|
|
||||||
/// No description provided for @top_product.
|
/// No description provided for @top_product.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -761,13 +761,13 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get profit_sharing => 'Profit Sharing';
|
String get profit_sharing => 'Profit Sharing';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get profit_sharing_desc => 'Revenue allocation for purchasing, owner, and team';
|
String get profit_sharing_desc => 'Revenue allocation for owner (SDL) and team';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get profit_sharing_allocation => 'Profit Sharing Allocation';
|
String get profit_sharing_allocation => 'Profit Sharing Allocation';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get share_purchase => 'Purchasing';
|
String get profit_sharing_not_team => 'This category is no longer part of profit sharing';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get share_owner => 'Owner';
|
String get share_owner => 'Owner';
|
||||||
@@ -778,6 +778,23 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get sdl => 'SDL';
|
String get sdl => 'SDL';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_summary => 'SDL Summary';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_desc => 'Owner\'s share of revenue';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_per_parent_category => 'SDL per Parent Category';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_per_week => 'SDL per Week';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String from_revenue(String revenue) {
|
||||||
|
return 'from $revenue revenue';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get top_product => 'Top Product';
|
String get top_product => 'Top Product';
|
||||||
|
|
||||||
|
|||||||
@@ -761,13 +761,13 @@ class AppLocalizationsId extends AppLocalizations {
|
|||||||
String get profit_sharing => 'Bagi Hasil';
|
String get profit_sharing => 'Bagi Hasil';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get profit_sharing_desc => 'Alokasi omzet untuk belanja, owner, dan tim';
|
String get profit_sharing_desc => 'Alokasi omzet untuk owner (SDL) dan tim';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get profit_sharing_allocation => 'Alokasi Bagi Hasil';
|
String get profit_sharing_allocation => 'Alokasi Bagi Hasil';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get share_purchase => 'Belanja';
|
String get profit_sharing_not_team => 'Kategori ini sudah tidak ikut bagi hasil';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get share_owner => 'Owner';
|
String get share_owner => 'Owner';
|
||||||
@@ -778,6 +778,23 @@ class AppLocalizationsId extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get sdl => 'SDL';
|
String get sdl => 'SDL';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_summary => 'Ringkasan SDL';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_desc => 'Bagian owner dari omzet';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_per_parent_category => 'SDL per Kategori Induk';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sdl_per_week => 'SDL per Minggu';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String from_revenue(String revenue) {
|
||||||
|
return 'dari omzet $revenue';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get top_product => 'Produk Terlaris';
|
String get top_product => 'Produk Terlaris';
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import '../../../common/theme/theme.dart';
|
|||||||
import '../../../domain/analytic/analytic.dart';
|
import '../../../domain/analytic/analytic.dart';
|
||||||
import '../../../injection.dart';
|
import '../../../injection.dart';
|
||||||
import '../../components/spacer/spacer.dart';
|
import '../../components/spacer/spacer.dart';
|
||||||
|
import 'widgets/period_label.dart';
|
||||||
import 'widgets/profit_sharing_allocation.dart';
|
import 'widgets/profit_sharing_allocation.dart';
|
||||||
import 'widgets/profit_sharing_detail_header.dart';
|
import 'widgets/profit_sharing_detail_header.dart';
|
||||||
|
import 'widgets/profit_sharing_sdl.dart';
|
||||||
import 'widgets/profit_sharing_status.dart';
|
import 'widgets/profit_sharing_status.dart';
|
||||||
import 'widgets/profit_sharing_subcategories.dart';
|
import 'widgets/profit_sharing_subcategories.dart';
|
||||||
|
|
||||||
@@ -48,7 +50,28 @@ class ProfitSharingDetailPage extends StatelessWidget
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColor.background,
|
backgroundColor: AppColor.background,
|
||||||
body:
|
body:
|
||||||
BlocBuilder<
|
BlocListener<
|
||||||
|
ProfitSharingDetailLoaderBloc,
|
||||||
|
ProfitSharingDetailLoaderState
|
||||||
|
>(
|
||||||
|
listenWhen: (previous, current) =>
|
||||||
|
previous.failureOption != current.failureOption,
|
||||||
|
listener: (context, state) {
|
||||||
|
final isNotTeam = state.failureOption.fold(
|
||||||
|
() => false,
|
||||||
|
(f) => f.maybeMap(notTeam: (_) => true, orElse: () => false),
|
||||||
|
);
|
||||||
|
// Kategori induk dimatikan dari team setelah list dimuat:
|
||||||
|
// kembali ke list dengan hasil `true` supaya list memuat ulang.
|
||||||
|
if (isNotTeam) context.router.maybePop(true);
|
||||||
|
},
|
||||||
|
child: _buildContent(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildContent() {
|
||||||
|
return BlocBuilder<
|
||||||
ProfitSharingDetailLoaderBloc,
|
ProfitSharingDetailLoaderBloc,
|
||||||
ProfitSharingDetailLoaderState
|
ProfitSharingDetailLoaderState
|
||||||
>(
|
>(
|
||||||
@@ -57,9 +80,7 @@ class ProfitSharingDetailPage extends StatelessWidget
|
|||||||
backgroundColor: AppColor.white,
|
backgroundColor: AppColor.white,
|
||||||
color: AppColor.primary,
|
color: AppColor.primary,
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
context.read<ProfitSharingDetailLoaderBloc>().add(
|
context.read<ProfitSharingDetailLoaderBloc>().add(_fetchEvent());
|
||||||
_fetchEvent(),
|
|
||||||
);
|
|
||||||
await context
|
await context
|
||||||
.read<ProfitSharingDetailLoaderBloc>()
|
.read<ProfitSharingDetailLoaderBloc>()
|
||||||
.stream
|
.stream
|
||||||
@@ -87,9 +108,13 @@ class ProfitSharingDetailPage extends StatelessWidget
|
|||||||
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: ProfitSharingAllocation(
|
child: _buildSdlSection(context, state.detail),
|
||||||
budget: state.detail.budget,
|
|
||||||
),
|
),
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: ProfitSharingAllocation(budget: state.detail.budget),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
@@ -113,7 +138,25 @@ class ProfitSharingDetailPage extends StatelessWidget
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSdlSection(BuildContext context, ProfitSharingDetail detail) {
|
||||||
|
final summary = detail.summary;
|
||||||
|
|
||||||
|
return ProfitSharingSdlSection(
|
||||||
|
sdl: summary.sdl,
|
||||||
|
revenue: summary.totalRevenue,
|
||||||
|
percent: summary.ownerFeePercent,
|
||||||
|
breakdownTitle: context.lang.sdl_per_week,
|
||||||
|
items: [
|
||||||
|
for (final period in detail.budget.weekly.where((e) => e.hasRevenue))
|
||||||
|
ProfitSharingSdlItem(
|
||||||
|
label: formatPeriodLabel(period.periodStart, period.periodEnd),
|
||||||
|
sdl: period.sdl,
|
||||||
|
revenue: period.revenue,
|
||||||
),
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +230,7 @@ class _SummaryCard extends StatelessWidget {
|
|||||||
icon: Icons.category_rounded,
|
icon: Icons.category_rounded,
|
||||||
label: context.lang.sub_category,
|
label: context.lang.sub_category,
|
||||||
value: '${summary.categoryCount}',
|
value: '${summary.categoryCount}',
|
||||||
|
color: ProfitSharingColor.subCategory,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SpaceWidth(10),
|
const SpaceWidth(10),
|
||||||
@@ -195,7 +239,7 @@ class _SummaryCard extends StatelessWidget {
|
|||||||
icon: Icons.inventory_2_rounded,
|
icon: Icons.inventory_2_rounded,
|
||||||
label: context.lang.products,
|
label: context.lang.products,
|
||||||
value: '${summary.productCount}',
|
value: '${summary.productCount}',
|
||||||
color: AppColor.info,
|
color: ProfitSharingColor.product,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SpaceWidth(10),
|
const SpaceWidth(10),
|
||||||
@@ -204,20 +248,13 @@ class _SummaryCard extends StatelessWidget {
|
|||||||
icon: Icons.receipt_long_rounded,
|
icon: Icons.receipt_long_rounded,
|
||||||
label: context.lang.orders,
|
label: context.lang.orders,
|
||||||
value: summary.orderCount.thousandFormat,
|
value: summary.orderCount.thousandFormat,
|
||||||
color: AppColor.warning,
|
color: ProfitSharingColor.order,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
const SpaceHeight(12),
|
const SpaceHeight(16),
|
||||||
|
|
||||||
ProfitSharingSdlStrip(
|
|
||||||
amount: summary.sdl,
|
|
||||||
feePercent: summary.ownerFeePercent,
|
|
||||||
),
|
|
||||||
|
|
||||||
const SpaceHeight(12),
|
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -4,15 +4,19 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:shimmer/shimmer.dart';
|
import 'package:shimmer/shimmer.dart';
|
||||||
|
|
||||||
import '../../../application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart';
|
import '../../../application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart';
|
||||||
|
import '../../../common/extension/extension.dart';
|
||||||
import '../../../common/theme/theme.dart';
|
import '../../../common/theme/theme.dart';
|
||||||
|
import '../../../domain/analytic/analytic.dart';
|
||||||
import '../../../injection.dart';
|
import '../../../injection.dart';
|
||||||
import '../../components/field/date_range_picker_field.dart';
|
import '../../components/field/date_range_picker_field.dart';
|
||||||
import '../../components/spacer/spacer.dart';
|
import '../../components/spacer/spacer.dart';
|
||||||
|
import '../../components/toast/flushbar.dart';
|
||||||
import '../../router/app_router.gr.dart';
|
import '../../router/app_router.gr.dart';
|
||||||
import 'widgets/profit_sharing_allocation.dart';
|
import 'widgets/profit_sharing_allocation.dart';
|
||||||
import 'widgets/profit_sharing_categories.dart';
|
import 'widgets/profit_sharing_categories.dart';
|
||||||
import 'widgets/profit_sharing_header.dart';
|
import 'widgets/profit_sharing_header.dart';
|
||||||
import 'widgets/profit_sharing_periods.dart';
|
import 'widgets/profit_sharing_periods.dart';
|
||||||
|
import 'widgets/profit_sharing_sdl.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class ProfitSharingPage extends StatefulWidget implements AutoRouteWrapper {
|
class ProfitSharingPage extends StatefulWidget implements AutoRouteWrapper {
|
||||||
@@ -124,15 +128,18 @@ class _ProfitSharingPageState extends State<ProfitSharingPage>
|
|||||||
opacity: _fadeAnimation,
|
opacity: _fadeAnimation,
|
||||||
child: ProfitSharingCategories(
|
child: ProfitSharingCategories(
|
||||||
categories: state.profitSharing.categories,
|
categories: state.profitSharing.categories,
|
||||||
onCategoryTap: (category) => context.router.push(
|
onCategoryTap: (category) =>
|
||||||
ProfitSharingDetailRoute(
|
_openDetail(context, state, category),
|
||||||
parentCategoryId: category.parentCategoryId,
|
|
||||||
parentCategoryName: category.parentCategoryName,
|
|
||||||
dateFrom: state.dateFrom,
|
|
||||||
dateTo: state.dateTo,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: _fadeAnimation,
|
||||||
|
child: _buildSdlSection(context, state),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -174,6 +181,58 @@ class _ProfitSharingPageState extends State<ProfitSharingPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Detail kembali dengan `true` kalau kategori induknya sudah non-team;
|
||||||
|
/// list dimuat ulang supaya kategori itu hilang.
|
||||||
|
Future<void> _openDetail(
|
||||||
|
BuildContext context,
|
||||||
|
ProfitSharingLoaderState state,
|
||||||
|
ProfitSharingCategory category,
|
||||||
|
) async {
|
||||||
|
final isNotTeam = await context.router.push<bool>(
|
||||||
|
ProfitSharingDetailRoute(
|
||||||
|
parentCategoryId: category.parentCategoryId,
|
||||||
|
parentCategoryName: category.parentCategoryName,
|
||||||
|
dateFrom: state.dateFrom,
|
||||||
|
dateTo: state.dateTo,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (isNotTeam != true || !context.mounted) return;
|
||||||
|
|
||||||
|
AppFlushbar.showError(context, context.lang.profit_sharing_not_team);
|
||||||
|
context.read<ProfitSharingLoaderBloc>().add(
|
||||||
|
const ProfitSharingLoaderEvent.fetched(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSdlSection(
|
||||||
|
BuildContext context,
|
||||||
|
ProfitSharingLoaderState state,
|
||||||
|
) {
|
||||||
|
final total = state.profitSharing.budget.total;
|
||||||
|
final categories = [...state.profitSharing.categories]
|
||||||
|
..sort((a, b) => b.sdl.compareTo(a.sdl));
|
||||||
|
|
||||||
|
return ProfitSharingSdlSection(
|
||||||
|
sdl: total.sdl,
|
||||||
|
revenue: total.revenue,
|
||||||
|
// Fee owner beda tiap kategori induk, jadi yang ditampilkan persen
|
||||||
|
// efektifnya; persentase bawaan hanya dipakai saat belum ada omzet.
|
||||||
|
percent: total.hasRevenue
|
||||||
|
? total.sdlPercentage
|
||||||
|
: state.profitSharing.budget.percentages.owner,
|
||||||
|
breakdownTitle: context.lang.sdl_per_parent_category,
|
||||||
|
items: [
|
||||||
|
for (final category in categories)
|
||||||
|
ProfitSharingSdlItem(
|
||||||
|
label: category.parentCategoryName,
|
||||||
|
sdl: category.sdl,
|
||||||
|
revenue: category.totalRevenue,
|
||||||
|
feePercent: category.ownerFeePercent,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildShimmer() {
|
Widget _buildShimmer() {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
|||||||
@@ -6,10 +6,20 @@ import '../../../../domain/analytic/analytic.dart';
|
|||||||
import '../../../components/spacer/spacer.dart';
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
|
||||||
/// Warna tetap untuk tiap pos bagi hasil supaya konsisten di semua bagian.
|
/// Warna tetap untuk tiap pos bagi hasil supaya konsisten di semua bagian.
|
||||||
|
/// Sengaja pakai warna jenuh, bukan default Material yang pucat.
|
||||||
class ProfitSharingColor {
|
class ProfitSharingColor {
|
||||||
static const Color purchase = Color(0xFF2196F3);
|
static const Color owner = Color(0xFF00B341);
|
||||||
static const Color owner = Color(0xFF4CAF50);
|
static const Color team = Color(0xFFFF6A00);
|
||||||
static const Color team = Color(0xFFFF9800);
|
|
||||||
|
// Status margin (Sehat / Waspada / Tidak Sehat).
|
||||||
|
static const Color healthy = Color(0xFF00B341);
|
||||||
|
static const Color watch = Color(0xFFFF9500);
|
||||||
|
static const Color critical = Color(0xFFFF1E3C);
|
||||||
|
|
||||||
|
// Tile ringkasan.
|
||||||
|
static const Color subCategory = AppColor.primary;
|
||||||
|
static const Color product = Color(0xFF7B2FF7);
|
||||||
|
static const Color order = Color(0xFF00A3D9);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProfitSharingAllocation extends StatelessWidget {
|
class ProfitSharingAllocation extends StatelessWidget {
|
||||||
@@ -21,11 +31,14 @@ class ProfitSharingAllocation extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final total = budget.total;
|
final total = budget.total;
|
||||||
final percentages = budget.percentages;
|
final percentages = budget.percentages;
|
||||||
// Fee owner berbeda tiap kategori induk, jadi porsi SDL dihitung dari
|
// Fee owner berbeda tiap kategori induk, jadi porsi dihitung dari
|
||||||
// nominalnya; persentase bawaan hanya dipakai saat belum ada omzet.
|
// nominalnya; persentase bawaan hanya dipakai saat belum ada omzet.
|
||||||
final sdlPercentage = total.hasRevenue
|
final sdlPercentage = total.hasRevenue
|
||||||
? total.sdlPercentage
|
? total.sdlPercentage
|
||||||
: percentages.owner;
|
: percentages.owner;
|
||||||
|
final teamPercentage = total.hasRevenue
|
||||||
|
? total.teamPercentage
|
||||||
|
: percentages.team;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
@@ -55,22 +68,10 @@ class ProfitSharingAllocation extends StatelessWidget {
|
|||||||
|
|
||||||
const SpaceHeight(16),
|
const SpaceHeight(16),
|
||||||
|
|
||||||
ProfitSharingBar(
|
ProfitSharingBar(owner: sdlPercentage, team: teamPercentage),
|
||||||
purchase: percentages.purchase,
|
|
||||||
owner: sdlPercentage,
|
|
||||||
team: percentages.team,
|
|
||||||
),
|
|
||||||
|
|
||||||
const SpaceHeight(20),
|
const SpaceHeight(20),
|
||||||
|
|
||||||
_row(
|
|
||||||
context: context,
|
|
||||||
color: ProfitSharingColor.purchase,
|
|
||||||
label: context.lang.share_purchase,
|
|
||||||
percentage: percentages.purchase,
|
|
||||||
amount: total.limitPurchase,
|
|
||||||
),
|
|
||||||
const Divider(height: 24, color: AppColor.borderLight),
|
|
||||||
_row(
|
_row(
|
||||||
context: context,
|
context: context,
|
||||||
color: ProfitSharingColor.owner,
|
color: ProfitSharingColor.owner,
|
||||||
@@ -83,7 +84,7 @@ class ProfitSharingAllocation extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
color: ProfitSharingColor.team,
|
color: ProfitSharingColor.team,
|
||||||
label: context.lang.share_team,
|
label: context.lang.share_team,
|
||||||
percentage: percentages.team,
|
percentage: teamPercentage,
|
||||||
amount: total.limitTeam,
|
amount: total.limitTeam,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -117,14 +118,14 @@ class ProfitSharingAllocation extends StatelessWidget {
|
|||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color.withOpacity(0.12),
|
color: color,
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${percentage.toStringAsFixed(percentage % 1 == 0 ? 0 : 1)}%',
|
'${percentage.toStringAsFixed(percentage % 1 == 0 ? 0 : 1)}%',
|
||||||
style: AppStyle.xs.copyWith(
|
style: AppStyle.xs.copyWith(
|
||||||
color: color,
|
color: AppColor.textWhite,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w800,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -145,16 +146,15 @@ class ProfitSharingAllocation extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bar proporsi belanja / SDL (owner) / tim.
|
/// Bar proporsi SDL (owner) / tim dalam persen omzet. Sisa yang belum terbagi
|
||||||
|
/// (backend lama masih menyisihkan porsi belanja) tampil sebagai track kosong.
|
||||||
class ProfitSharingBar extends StatelessWidget {
|
class ProfitSharingBar extends StatelessWidget {
|
||||||
final double purchase;
|
|
||||||
final double owner;
|
final double owner;
|
||||||
final double team;
|
final double team;
|
||||||
final double height;
|
final double height;
|
||||||
|
|
||||||
const ProfitSharingBar({
|
const ProfitSharingBar({
|
||||||
super.key,
|
super.key,
|
||||||
required this.purchase,
|
|
||||||
required this.owner,
|
required this.owner,
|
||||||
required this.team,
|
required this.team,
|
||||||
this.height = 12,
|
this.height = 12,
|
||||||
@@ -162,7 +162,7 @@ class ProfitSharingBar extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final total = purchase + owner + team;
|
final total = owner + team;
|
||||||
if (total <= 0) {
|
if (total <= 0) {
|
||||||
return Container(
|
return Container(
|
||||||
height: height,
|
height: height,
|
||||||
@@ -179,9 +179,9 @@ class ProfitSharingBar extends StatelessWidget {
|
|||||||
height: height,
|
height: height,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
_segment(purchase, ProfitSharingColor.purchase),
|
|
||||||
_segment(owner, ProfitSharingColor.owner),
|
_segment(owner, ProfitSharingColor.owner),
|
||||||
_segment(team, ProfitSharingColor.team),
|
_segment(team, ProfitSharingColor.team),
|
||||||
|
_segment(100 - total, AppColor.borderLight),
|
||||||
].whereType<Widget>().toList(),
|
].whereType<Widget>().toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import '../../../../common/extension/extension.dart';
|
|||||||
import '../../../../common/theme/theme.dart';
|
import '../../../../common/theme/theme.dart';
|
||||||
import '../../../../domain/analytic/analytic.dart';
|
import '../../../../domain/analytic/analytic.dart';
|
||||||
import '../../../components/spacer/spacer.dart';
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
import 'profit_sharing_allocation.dart';
|
||||||
import 'profit_sharing_status.dart';
|
import 'profit_sharing_status.dart';
|
||||||
|
|
||||||
/// Ringkasan omzet & SDL per kategori induk (parent category).
|
/// Ringkasan porsi tim (omzet − SDL) per kategori induk (parent category).
|
||||||
/// Tiap kartu bisa diketuk untuk melihat rincian sub kategori & produknya.
|
/// Tiap kartu bisa diketuk untuk melihat rincian sub kategori & produknya.
|
||||||
class ProfitSharingCategories extends StatelessWidget {
|
class ProfitSharingCategories extends StatelessWidget {
|
||||||
final List<ProfitSharingCategory> categories;
|
final List<ProfitSharingCategory> categories;
|
||||||
@@ -21,9 +22,9 @@ class ProfitSharingCategories extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final sorted = [...categories]
|
final sorted = [...categories]
|
||||||
..sort((a, b) => b.totalRevenue.compareTo(a.totalRevenue));
|
..sort((a, b) => b.teamShare.compareTo(a.teamShare));
|
||||||
|
|
||||||
final totalRevenue = sorted.fold<int>(0, (sum, e) => sum + e.totalRevenue);
|
final totalTeam = sorted.fold<int>(0, (sum, e) => sum + e.teamShare);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
@@ -75,9 +76,7 @@ class ProfitSharingCategories extends StatelessWidget {
|
|||||||
child: _CategoryCard(
|
child: _CategoryCard(
|
||||||
rank: i + 1,
|
rank: i + 1,
|
||||||
category: sorted[i],
|
category: sorted[i],
|
||||||
share: totalRevenue == 0
|
share: totalTeam == 0 ? 0 : sorted[i].teamShare / totalTeam,
|
||||||
? 0
|
|
||||||
: sorted[i].totalRevenue / totalRevenue,
|
|
||||||
onTap: () => onCategoryTap(sorted[i]),
|
onTap: () => onCategoryTap(sorted[i]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -106,18 +105,11 @@ class _CategoryCard extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isTop = rank == 1;
|
final isTop = rank == 1;
|
||||||
|
|
||||||
return Material(
|
return ProfitSharingItemCard(
|
||||||
color: AppColor.background,
|
|
||||||
borderRadius: BorderRadius.circular(14),
|
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
borderRadius: BorderRadius.circular(14),
|
child: Padding(
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(14),
|
padding: const EdgeInsets.all(14),
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(14),
|
|
||||||
border: Border.all(color: AppColor.borderLight),
|
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -188,7 +180,7 @@ class _CategoryCard extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
category.totalRevenue.currencyFormatRp,
|
category.teamShare.currencyFormatRp,
|
||||||
style: AppStyle.xl.copyWith(
|
style: AppStyle.xl.copyWith(
|
||||||
color: AppColor.textPrimary,
|
color: AppColor.textPrimary,
|
||||||
fontWeight: FontWeight.w800,
|
fontWeight: FontWeight.w800,
|
||||||
@@ -204,21 +196,53 @@ class _CategoryCard extends StatelessWidget {
|
|||||||
vertical: 3,
|
vertical: 3,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColor.primary.withOpacity(0.08),
|
color: AppColor.primary,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
formatPercent(share * 100),
|
formatPercent(share * 100),
|
||||||
style: AppStyle.xs.copyWith(
|
style: AppStyle.xs.copyWith(
|
||||||
color: AppColor.primary,
|
color: AppColor.textWhite,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w800,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
const SpaceHeight(8),
|
const SpaceHeight(4),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.share_team,
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: ProfitSharingColor.team,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(4),
|
||||||
|
ProfitSharingFeeBadge(
|
||||||
|
feePercent: category.teamPercent,
|
||||||
|
color: ProfitSharingColor.team,
|
||||||
|
),
|
||||||
|
const SpaceWidth(6),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
context.lang.from_revenue(
|
||||||
|
category.totalRevenue.currencyFormatRp,
|
||||||
|
),
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: AppColor.textSecondary,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(10),
|
||||||
|
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
@@ -232,15 +256,8 @@ class _CategoryCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SpaceHeight(12),
|
|
||||||
|
|
||||||
ProfitSharingSdlStrip(
|
|
||||||
amount: category.sdl,
|
|
||||||
feePercent: category.ownerFeePercent,
|
|
||||||
),
|
|
||||||
|
|
||||||
if (category.hasTopProduct) ...[
|
if (category.hasTopProduct) ...[
|
||||||
const SpaceHeight(10),
|
const SpaceHeight(12),
|
||||||
_TopProduct(product: category.topProduct),
|
_TopProduct(product: category.topProduct),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -333,7 +350,7 @@ class _TotalCard extends StatelessWidget {
|
|||||||
0,
|
0,
|
||||||
(sum, e) => sum + e.totalRevenue,
|
(sum, e) => sum + e.totalRevenue,
|
||||||
);
|
);
|
||||||
final totalSdl = categories.fold<int>(0, (sum, e) => sum + e.sdl);
|
final totalTeam = categories.fold<int>(0, (sum, e) => sum + e.teamShare);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
@@ -349,7 +366,8 @@ class _TotalCard extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
context.lang.grand_total,
|
'${context.lang.grand_total} '
|
||||||
|
'${context.lang.share_team.toUpperCase()}',
|
||||||
style: AppStyle.xs.copyWith(
|
style: AppStyle.xs.copyWith(
|
||||||
color: AppColor.textWhite.withOpacity(0.8),
|
color: AppColor.textWhite.withOpacity(0.8),
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
@@ -358,7 +376,7 @@ class _TotalCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
totalRevenue.currencyFormatRp,
|
totalTeam.currencyFormatRp,
|
||||||
style: AppStyle.xl.copyWith(
|
style: AppStyle.xl.copyWith(
|
||||||
color: AppColor.textWhite,
|
color: AppColor.textWhite,
|
||||||
fontWeight: FontWeight.w900,
|
fontWeight: FontWeight.w900,
|
||||||
@@ -369,8 +387,8 @@ class _TotalCard extends StatelessWidget {
|
|||||||
|
|
||||||
ProfitSharingHeaderStats(
|
ProfitSharingHeaderStats(
|
||||||
stats: [
|
stats: [
|
||||||
|
(context.lang.revenue, totalRevenue.currencyFormatRp),
|
||||||
(context.lang.qty, totalQuantity.thousandFormat),
|
(context.lang.qty, totalQuantity.thousandFormat),
|
||||||
(context.lang.sdl, totalSdl.currencyFormatRp),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import '../../../../domain/analytic/analytic.dart';
|
|||||||
import '../../../components/spacer/spacer.dart';
|
import '../../../components/spacer/spacer.dart';
|
||||||
import 'period_label.dart';
|
import 'period_label.dart';
|
||||||
import 'profit_sharing_allocation.dart';
|
import 'profit_sharing_allocation.dart';
|
||||||
|
import 'profit_sharing_status.dart';
|
||||||
|
|
||||||
class ProfitSharingPeriods extends StatelessWidget {
|
class ProfitSharingPeriods extends StatelessWidget {
|
||||||
final ProfitSharingLoaderState state;
|
final ProfitSharingLoaderState state;
|
||||||
@@ -151,13 +152,9 @@ class _PeriodCard extends StatelessWidget {
|
|||||||
? '${formatPeriodLabel(period.periodStart, period.periodEnd)} - ${context.lang.week_count(period.weekCount)}'
|
? '${formatPeriodLabel(period.periodStart, period.periodEnd)} - ${context.lang.week_count(period.weekCount)}'
|
||||||
: context.lang.order_count_label(period.orderCount);
|
: context.lang.order_count_label(period.orderCount);
|
||||||
|
|
||||||
return Container(
|
return ProfitSharingItemCard(
|
||||||
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: AppColor.background,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: AppColor.borderLight),
|
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -199,9 +196,12 @@ class _PeriodCard extends StatelessWidget {
|
|||||||
const SpaceHeight(12),
|
const SpaceHeight(12),
|
||||||
|
|
||||||
ProfitSharingBar(
|
ProfitSharingBar(
|
||||||
purchase: percentages.purchase,
|
owner: period.hasRevenue
|
||||||
owner: period.hasRevenue ? period.sdlPercentage : percentages.owner,
|
? period.sdlPercentage
|
||||||
team: percentages.team,
|
: percentages.owner,
|
||||||
|
team: period.hasRevenue
|
||||||
|
? period.teamPercentage
|
||||||
|
: percentages.team,
|
||||||
height: 6,
|
height: 6,
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -209,11 +209,6 @@ class _PeriodCard extends StatelessWidget {
|
|||||||
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
_share(
|
|
||||||
context.lang.share_purchase,
|
|
||||||
period.limitPurchase,
|
|
||||||
ProfitSharingColor.purchase,
|
|
||||||
),
|
|
||||||
_share(context.lang.sdl, period.sdl, ProfitSharingColor.owner),
|
_share(context.lang.sdl, period.sdl, ProfitSharingColor.owner),
|
||||||
_share(
|
_share(
|
||||||
context.lang.share_team,
|
context.lang.share_team,
|
||||||
@@ -224,6 +219,7 @@ class _PeriodCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,283 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
import 'profit_sharing_allocation.dart';
|
||||||
|
import 'profit_sharing_status.dart';
|
||||||
|
|
||||||
|
/// Satu baris rincian SDL, bisa per kategori induk atau per periode.
|
||||||
|
class ProfitSharingSdlItem {
|
||||||
|
final String label;
|
||||||
|
final int sdl;
|
||||||
|
final int revenue;
|
||||||
|
final double? feePercent;
|
||||||
|
|
||||||
|
const ProfitSharingSdlItem({
|
||||||
|
required this.label,
|
||||||
|
required this.sdl,
|
||||||
|
required this.revenue,
|
||||||
|
this.feePercent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Section khusus SDL (bagian owner): total di blok hijau, lalu rinciannya.
|
||||||
|
/// Urutan [items] ditampilkan apa adanya.
|
||||||
|
class ProfitSharingSdlSection extends StatelessWidget {
|
||||||
|
final int sdl;
|
||||||
|
final int revenue;
|
||||||
|
|
||||||
|
/// Persen di blok total: fee owner kalau satu kategori, atau persen
|
||||||
|
/// efektif terhadap omzet kalau gabungan beberapa kategori.
|
||||||
|
final double percent;
|
||||||
|
final String breakdownTitle;
|
||||||
|
final List<ProfitSharingSdlItem> items;
|
||||||
|
|
||||||
|
const ProfitSharingSdlSection({
|
||||||
|
super.key,
|
||||||
|
required this.sdl,
|
||||||
|
required this.revenue,
|
||||||
|
required this.percent,
|
||||||
|
required this.breakdownTitle,
|
||||||
|
this.items = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final totalSdl = items.fold<int>(0, (sum, e) => sum + e.sdl);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.textLight.withOpacity(0.08),
|
||||||
|
spreadRadius: 1,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.sdl_summary,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
context.lang.sdl_desc,
|
||||||
|
style: AppStyle.xs.copyWith(color: AppColor.textSecondary),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
_TotalBlock(sdl: sdl, revenue: revenue, percent: percent),
|
||||||
|
|
||||||
|
if (items.isNotEmpty) ...[
|
||||||
|
const SpaceHeight(20),
|
||||||
|
Text(
|
||||||
|
breakdownTitle,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceHeight(12),
|
||||||
|
for (var i = 0; i < items.length; i++) ...[
|
||||||
|
if (i > 0) const Divider(height: 24, color: AppColor.borderLight),
|
||||||
|
_SdlRow(
|
||||||
|
item: items[i],
|
||||||
|
share: totalSdl == 0 ? 0 : items[i].sdl / totalSdl,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TotalBlock extends StatelessWidget {
|
||||||
|
final int sdl;
|
||||||
|
final int revenue;
|
||||||
|
final double percent;
|
||||||
|
|
||||||
|
const _TotalBlock({
|
||||||
|
required this.sdl,
|
||||||
|
required this.revenue,
|
||||||
|
required this.percent,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const color = ProfitSharingColor.owner;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [color, darken(color)],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(14),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: color.withOpacity(0.3),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.2),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.account_balance_wallet_rounded,
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(10),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
context.lang.sdl,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ProfitSharingFeeBadge(
|
||||||
|
feePercent: percent,
|
||||||
|
onDarkBackground: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SpaceHeight(14),
|
||||||
|
FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
sdl.currencyFormatRp,
|
||||||
|
style: AppStyle.h3.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
context.lang.from_revenue(revenue.currencyFormatRp),
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.85),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SdlRow extends StatelessWidget {
|
||||||
|
final ProfitSharingSdlItem item;
|
||||||
|
|
||||||
|
/// Porsi baris ini terhadap total SDL di daftar (0..1).
|
||||||
|
final double share;
|
||||||
|
|
||||||
|
const _SdlRow({required this.item, required this.share});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final amountColor = darken(ProfitSharingColor.owner);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
item.label,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (item.feePercent != null) ...[
|
||||||
|
const SpaceWidth(6),
|
||||||
|
ProfitSharingFeeBadge(feePercent: item.feePercent!),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
Text(
|
||||||
|
item.sdl.currencyFormatRp,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: amountColor,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SpaceHeight(8),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
value: share.clamp(0.0, 1.0),
|
||||||
|
minHeight: 6,
|
||||||
|
backgroundColor: AppColor.border,
|
||||||
|
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||||
|
ProfitSharingColor.owner,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceHeight(6),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
context.lang.from_revenue(item.revenue.currencyFormatRp),
|
||||||
|
style: AppStyle.xs.copyWith(color: AppColor.textSecondary),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
formatPercent(share * 100),
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: amountColor,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,10 +18,16 @@ String formatPercent(double value) => '${value.toStringAsFixed(1)}%';
|
|||||||
String formatFeePercent(double value) =>
|
String formatFeePercent(double value) =>
|
||||||
'${value.toStringAsFixed(value % 1 == 0 ? 0 : 1)}%';
|
'${value.toStringAsFixed(value % 1 == 0 ? 0 : 1)}%';
|
||||||
|
|
||||||
|
/// Versi lebih gelap dari [color], dipakai sebagai ujung gradien.
|
||||||
|
Color darken(Color color, [double amount = 0.2]) =>
|
||||||
|
Color.lerp(color, AppColor.black, amount)!;
|
||||||
|
|
||||||
Color statusColor(double realHppPercentage) {
|
Color statusColor(double realHppPercentage) {
|
||||||
if (realHppPercentage <= HppThreshold.healthy) return AppColor.success;
|
if (realHppPercentage <= HppThreshold.healthy) {
|
||||||
if (realHppPercentage <= HppThreshold.watch) return AppColor.warning;
|
return ProfitSharingColor.healthy;
|
||||||
return AppColor.error;
|
}
|
||||||
|
if (realHppPercentage <= HppThreshold.watch) return ProfitSharingColor.watch;
|
||||||
|
return ProfitSharingColor.critical;
|
||||||
}
|
}
|
||||||
|
|
||||||
String statusLabel(BuildContext context, double realHppPercentage) {
|
String statusLabel(BuildContext context, double realHppPercentage) {
|
||||||
@@ -47,96 +53,94 @@ class ProfitSharingStatusBadge extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final color = statusColor(realHppPercentage);
|
final color = statusColor(realHppPercentage);
|
||||||
|
|
||||||
|
// Di atas header merah, pill putih supaya status merah tidak tenggelam.
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: onDarkBackground
|
color: onDarkBackground ? AppColor.white : color,
|
||||||
? AppColor.textWhite.withOpacity(0.18)
|
|
||||||
: color.withOpacity(0.12),
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: onDarkBackground
|
|
||||||
? Border.all(color: AppColor.textWhite.withOpacity(0.3))
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
statusLabel(context, realHppPercentage),
|
statusLabel(context, realHppPercentage),
|
||||||
style: AppStyle.xs.copyWith(
|
style: AppStyle.xs.copyWith(
|
||||||
color: onDarkBackground ? AppColor.textWhite : color,
|
color: onDarkBackground ? color : AppColor.textWhite,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w800,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Strip sorotan SDL: label + persen fee owner di kiri, nominal di kanan.
|
/// Kartu item di dalam section: latar putih, garis aksen berwarna di kiri.
|
||||||
class ProfitSharingSdlStrip extends StatelessWidget {
|
/// Child boleh berisi InkWell; ripple-nya ikut terpotong sudut kartu.
|
||||||
final int amount;
|
class ProfitSharingItemCard extends StatelessWidget {
|
||||||
final double? feePercent;
|
final Widget child;
|
||||||
|
final Color accentColor;
|
||||||
|
|
||||||
const ProfitSharingSdlStrip({
|
const ProfitSharingItemCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.amount,
|
required this.child,
|
||||||
this.feePercent,
|
this.accentColor = AppColor.primary,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const color = ProfitSharingColor.owner;
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
clipBehavior: Clip.antiAlias,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color.withOpacity(0.08),
|
color: AppColor.white,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(14),
|
||||||
border: Border.all(color: color.withOpacity(0.2)),
|
border: Border.all(color: AppColor.border),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.black.withOpacity(0.05),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
),
|
),
|
||||||
child: Row(
|
],
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
Material(type: MaterialType.transparency, child: child),
|
||||||
Icons.account_balance_wallet_rounded,
|
Positioned(
|
||||||
color: color,
|
left: 0,
|
||||||
size: 18,
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
child: Container(width: 4, color: accentColor),
|
||||||
),
|
),
|
||||||
const SpaceWidth(8),
|
],
|
||||||
Text(
|
|
||||||
context.lang.sdl,
|
|
||||||
style: AppStyle.sm.copyWith(
|
|
||||||
color: AppColor.textPrimary,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
if (feePercent != null) ...[
|
}
|
||||||
const SpaceWidth(6),
|
}
|
||||||
Container(
|
|
||||||
|
/// Pill persen fee owner. Di atas latar berwarna jadi putih supaya terbaca.
|
||||||
|
class ProfitSharingFeeBadge extends StatelessWidget {
|
||||||
|
final double feePercent;
|
||||||
|
final Color color;
|
||||||
|
final bool onDarkBackground;
|
||||||
|
|
||||||
|
const ProfitSharingFeeBadge({
|
||||||
|
super.key,
|
||||||
|
required this.feePercent,
|
||||||
|
this.color = ProfitSharingColor.owner,
|
||||||
|
this.onDarkBackground = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color,
|
color: onDarkBackground ? AppColor.white : color,
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
formatFeePercent(feePercent!),
|
formatFeePercent(feePercent),
|
||||||
style: AppStyle.xs.copyWith(
|
style: AppStyle.xs.copyWith(
|
||||||
color: AppColor.textWhite,
|
color: onDarkBackground ? color : AppColor.textWhite,
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const SpaceWidth(8),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
amount.currencyFormatRp,
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
style: AppStyle.md.copyWith(
|
|
||||||
color: AppColor.secondaryDark,
|
|
||||||
fontWeight: FontWeight.w800,
|
fontWeight: FontWeight.w800,
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -205,7 +209,7 @@ class ProfitSharingHeaderStats extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Kotak statistik kecil: ikon, nilai, lalu label.
|
/// Kartu statistik kecil berwarna solid: ikon, nilai, lalu label.
|
||||||
class ProfitSharingStatTile extends StatelessWidget {
|
class ProfitSharingStatTile extends StatelessWidget {
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
final String label;
|
final String label;
|
||||||
@@ -225,9 +229,19 @@ class ProfitSharingStatTile extends StatelessWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColor.background,
|
gradient: LinearGradient(
|
||||||
|
colors: [color, darken(color)],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
border: Border.all(color: AppColor.borderLight),
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: color.withOpacity(0.3),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: const Offset(0, 3),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -236,25 +250,30 @@ class ProfitSharingStatTile extends StatelessWidget {
|
|||||||
width: 30,
|
width: 30,
|
||||||
height: 30,
|
height: 30,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color.withOpacity(0.1),
|
color: AppColor.textWhite.withOpacity(0.2),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Icon(icon, color: color, size: 16),
|
child: Icon(icon, color: AppColor.textWhite, size: 16),
|
||||||
),
|
),
|
||||||
const SpaceHeight(10),
|
const SpaceHeight(10),
|
||||||
Text(
|
FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
value,
|
value,
|
||||||
style: AppStyle.lg.copyWith(
|
style: AppStyle.lg.copyWith(
|
||||||
color: AppColor.textPrimary,
|
color: AppColor.textWhite,
|
||||||
fontWeight: FontWeight.w800,
|
fontWeight: FontWeight.w800,
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: AppStyle.xs.copyWith(color: AppColor.textSecondary),
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.85),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -99,17 +99,11 @@ class _SubCategoryCard extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return ProfitSharingItemCard(
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: AppColor.background,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: AppColor.borderLight),
|
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: onToggle,
|
onTap: onToggle,
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(14),
|
padding: const EdgeInsets.all(14),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -155,7 +149,7 @@ class _SubCategoryCard extends StatelessWidget {
|
|||||||
child: LinearProgressIndicator(
|
child: LinearProgressIndicator(
|
||||||
value: share.clamp(0.0, 1.0),
|
value: share.clamp(0.0, 1.0),
|
||||||
minHeight: 5,
|
minHeight: 5,
|
||||||
backgroundColor: AppColor.borderLight,
|
backgroundColor: AppColor.border,
|
||||||
valueColor: const AlwaysStoppedAnimation<Color>(
|
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||||
AppColor.primary,
|
AppColor.primary,
|
||||||
),
|
),
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ description: "A new Flutter project."
|
|||||||
|
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.0.4+13
|
version: 1.0.4+14
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.8.1
|
sdk: ^3.8.1
|
||||||
|
|||||||
Reference in New Issue
Block a user