dstpabuaran.com/.ai/REFERENCE.md
Yoga Pangestu 49841a662c Refactor marketplace settings: remove MarketplaceFeeRule, update related database and UI components
- Deleted MarketplaceFeeRule class and its usage in settings migration.
- Removed 'is_affiliate' field from orders and related factories.
- Updated notifications table to use longText for body.
- Adjusted role permissions by removing marketplace-related permissions.
- Cleaned up admin settings page by removing marketplace settings section and related components.
- Updated tests to reflect the removal of marketplace settings and ensure other settings remain unaffected.
2026-08-14 03:20:18 +07:00

27 KiB

Database Reference

Format: table_namemodel_name | columns | relationships


Auth & User

users → User

id email(unique) username(unique) password is_active(bool) last_login_at(datetime) created_at updated_at deleted_at

  • Casts: email_verified_at(datetime), is_active(bool), last_login_at(datetime), password(hashed), two_factor_confirmed_at(datetime)
  • Implements: HasMedia (Spatie Media Library)
  • Media Collections: photos (single photo, with thumb conversion)
  • Scopes: active()
  • Relations: userProfile(HasOne→UserProfile), employee(HasOne→Employee), attendances(HasMany→Attendance), cashAccounts(HasMany→CashAccount,created_by_id), cashTransactions(HasMany→CashTransaction,created_by_id), createdCuttings(HasMany→Cutting,created_by_id), createdExpenses(HasMany→Expense,created_by_id), createdOrders(HasMany→Order,created_by_id), marketingOrders(HasMany→Order,marketing_id), orderItems(HasMany→OrderItem), createdPurchases(HasMany→Purchase,created_by_id), createdRestocks(HasMany→Restock,created_by_id), stokOpnamesCreated(HasMany→StokOpname,created_by_id), stokOpnamesVerified(HasMany→StokOpname,verified_by_id), employeeAdvancesPaid(HasMany→EmployeeAdvance,paid_by_id), employeeAdvancesVerified(HasMany→EmployeeAdvance,verified_by_id), paidPayrolls(HasMany→Payroll,paid_by_id), payrollPeriodsClosed(HasMany→PayrollPeriod,closed_by_id), notifications(HasMany→AppNotification), rejections(HasMany→Rejection,rejected_by_id), pushSubscriptions(HasMany→PushSubscription,morph)
  • Accessor: avatar → temporary S3 URL dari media 'photos' (atau null)

user_profiles → UserProfile

id user_id(FK→users,unique) full_name(200) phone_number(20,null) gender(enum,null) birth_date(date,null) address(text,null) created_at updated_at deleted_at

  • Casts: gender(Gender), birth_date(date:Y-m-d)
  • Scopes: female(), male(), hasPhoneNumber()
  • Relations: user(BelongsTo→User)

push_subscriptions → PushSubscription

id subscribable_type subscribable_id endpoint(500,unique) public_key(null) auth_token(null) content_encoding(null) created_at updated_at

  • Relations: user(MorphTo)

notifications → AppNotification

id user_id(FK→users) title body(longText,null) url(null) is_read(bool,default:false) read_at(datetime,null) created_at updated_at

  • Casts: is_read(bool), read_at(datetime)
  • Accessor: formatted_read_at → 'l, d F Y H:i'
  • Relations: user(BelongsTo→User)

Master Data

categories → Category

id name(50) slug(50,unique) created_at updated_at deleted_at

  • Relations: products(BelongsToMany→Product via product_categories)
  • Accessor: formattedName → ucfirst(name)

product_categories → Category (Pivot)

product_id(FK→products) category_id(FK→categories)

  • No id, no timestamps
  • Relations: category(BelongsTo→Category), product(BelongsTo→Product)

products → Product

id name(200) slug(200,unique) description(text,null) status(enum,default:active) is_featured(bool,default:false) rejection_reason(text,null) created_at updated_at deleted_at

  • Casts: status(ProductStatus), is_featured(bool)
  • Scopes: active(), draft(), featured(), inactive(), pending(), rejected()
  • Relations: categories(BelongsToMany→Category), productVariants(HasMany→ProductVariant)

product_variants → ProductVariant

id product_id(FK→products) name(200) stock(uint,default:0) reject_stock(uint,default:0) retail_stock(uint,default:0) created_at updated_at deleted_at

  • Casts: stock(int), reject_stock(int), retail_stock(int)
  • GlobalScope: orderBy(name)
  • Relations: product(BelongsTo→Product), productPrices(HasMany→ProductPrice,variant_id), orderItems(HasMany→OrderItem), restockItems(HasMany→RestockItem), retailStockHistories(HasMany→RetailStockHistory), stokOpnameItems(HasMany→StokOpnameItem), stockMutations(HasMany→StockMutation,morph)

product_prices → ProductPrice

id variant_id(FK→product_variants) type(enum) price(uint) created_at updated_at

  • UNIQUE(variant_id, type)
  • Casts: type(PriceType), price(int)
  • Scopes: retail(), wholesale()
  • Relations: variant(BelongsTo→ProductVariant)

customers → Customer

id name(200) phone_number(20,null) address(text,null) created_at updated_at deleted_at

  • Relations: orders(HasMany→Order)
  • Accessor: formattedPhoneNumber (get: "0821 2121 2121", set: strip whitespace)

suppliers → Supplier

id name(200) phone_number(20,null) address(text,null) created_at updated_at deleted_at

  • Relations: purchases(HasMany→Purchase)
  • Accessor: formattedPhoneNumber (get: "0821 2121 2121", set: strip whitespace)

raw_materials → RawMaterial

id name(200) unit(enum) is_active(bool,default:true) created_at updated_at deleted_at

  • Casts: unit(RawMaterialUnit), is_active(bool)
  • Scopes: active(), nonactive(), kg(), meter(), yard()
  • Relations: rawMaterialPrices(HasMany→RawMaterialPrice)

raw_material_prices → RawMaterialPrice

id raw_material_id(FK→raw_materials) variant(200) price(uint) stock(uint,default:0) created_at updated_at deleted_at

  • Casts: price(int), stock(int)
  • GlobalScope: orderBy(variant)
  • Relations: rawMaterial(BelongsTo→RawMaterial,withTrashed), cuttingMaterials(HasMany→CuttingMaterial), purchaseItems(HasMany→PurchaseItem)
  • Accessor: photo_url → first media presigned S3 URL

Finance

cash_accounts → CashAccount

id created_by_id(FK→users) name(200) balance(ubig,default:0) created_at updated_at deleted_at

  • Casts: balance(int)
  • Relations: cashTransactions(HasMany→CashTransaction), createdBy(BelongsTo→User)

cash_transactions → CashTransaction

id cash_account_id(FK→cash_accounts) created_by_id(FK→users) reference_id(ubig,null,morph) reference_type(string,null,morph) amount(ubig) balance_after(ubig) type(enum,default:deposit) description(100) created_at updated_at deleted_at

  • Casts: type(CashTransactionType), amount(int), balance_after(int)
  • Scopes: deposit(), expenseType(), transfer(), withdrawal()
  • Relations: cashAccount(BelongsTo→CashAccount), createdBy(BelongsTo→User), reference(MorphTo), expense(HasOne→Expense), order(HasOne→Order), employeeAdvances(HasMany→EmployeeAdvance), payrolls(HasMany→Payroll)

expenses → Expense

id cash_transaction_id(FK→cash_transactions,unique,null) created_by_id(FK→users) amount(ubig) description(100) created_at updated_at deleted_at

  • Casts: amount(int), date(date:Y-m-d)
  • Relations: cashTransaction(BelongsTo→CashTransaction), createdBy(BelongsTo→User)

employee_advances → EmployeeAdvance

id paid_by_id(FK→users,null) employee_id(FK→employees) verified_by_id(FK→users,null) repayment_cash_transaction_id(FK→cash_transactions,unique,null) cash_transaction_id(FK→cash_transactions,unique,null) amount(ubig) paid_amount(ubig,default:0) description(100) due_date(date) status(enum,default:pending) verified_at(datetime,null) paid_at(datetime,null) created_at updated_at deleted_at

  • Casts: status(EmployeeAdvanceStatus), amount(int), paid_amount(int), due_date(date:Y-m-d), verified_at(datetime), paid_at(datetime)
  • Scopes: approved(), cancelled(), paid(), pending(), rejected()
  • Relations: employee(BelongsTo→Employee), cashTransaction(BelongsTo→CashTransaction), repaymentCashTransaction(BelongsTo→CashTransaction), paidBy(BelongsTo→User), verifiedBy(BelongsTo→User), payments(HasMany→EmployeeAdvancePayment)

employee_advance_payments → EmployeeAdvancePayment

id employee_advance_id(FK→employee_advances) paid_by_id(FK→users,null) cash_transaction_id(FK→cash_transactions,unique,null) amount(ubig) description(100,null) paid_at(datetime) created_at updated_at

  • No soft deletes
  • Casts: amount(int), paid_at(datetime)
  • Accessor: formatted_amount → 'Rp X.XXX', formatted_paid_at → 'l, d F Y H:i'
  • Relations: employeeAdvance(BelongsTo→EmployeeAdvance), paidBy(BelongsTo→User), cashTransaction(BelongsTo→CashTransaction)

HR

employees → Employee

id user_id(FK→users,unique) join_date(date) resign_date(date,null) employment_status(enum,default:full_time) base_salary(uint) created_at updated_at deleted_at

  • Casts: employment_status(EmploymentStatus), base_salary(int), join_date(date:Y-m-d), resign_date(date:Y-m-d)
  • Scopes: contract(), fullTime(), internship(), partTime(), resigned()
  • Relations: user(BelongsTo→User), attendances(HasMany→Attendance), employeeAdvances(HasMany→EmployeeAdvance), leaveRequests(HasMany→LeaveRequest), payrolls(HasMany→Payroll)

attendances → Attendance

id employee_id(FK→employees) attendance_date(date) check_in_at(datetime) check_out_at(datetime,null) check_in_latitude(decimal(10,7),null) check_in_longitude(decimal(10,7),null) check_out_latitude(decimal(10,7),null) check_out_longitude(decimal(10,7),null) work_duration_minutes(uint,null) created_at updated_at

  • No soft deletes
  • Casts: attendance_date(date:Y-m-d), check_in_at(datetime), check_out_at(datetime), check_in/out_latitude/longitude(decimal:7), work_duration_minutes(int)
  • Accessor: formatted_attendance_date → 'l, d F Y', formatted_check_in_at → 'l, d F Y H:i', formatted_check_out_at → 'l, d F Y H:i'
  • Relations: employee(BelongsTo→Employee), payrollAdjustments(HasMany→PayrollAdjustment)

payroll_periods → PayrollPeriod

id closed_by_id(FK→users,null) year(usmall) month(utiny) status(enum,default:open) closed_at(datetime,null) created_at updated_at deleted_at

  • Casts: status(PayrollPeriodStatus), year(int), month(int), closed_at(datetime)
  • Accessor: formatted_closed_at → 'l, d F Y H:i', month_name → 'Januari', status_label
  • Scopes: closed(), open()
  • Relations: closedBy(BelongsTo→User), payrolls(HasMany→Payroll)

payrolls → Payroll

id payroll_period_id(FK→payroll_periods) employee_id(FK→employees) cash_transaction_id(FK→cash_transactions,unique,null) paid_by_id(FK→users,null) base_salary(uint) bonus_amount(ubig,default:0) deduction_amount(ubig,default:0) total_amount(ubig) status(enum,default:unpaid) paid_at(datetime,null) created_at updated_at deleted_at

  • Casts: status(PayrollStatus), base_salary(int), bonus_amount(int), deduction_amount(int), total_amount(int), paid_at(datetime)
  • Scopes: cancelled(), paid(), unpaid()
  • Relations: payrollPeriod(BelongsTo→PayrollPeriod), employee(BelongsTo→Employee), cashTransaction(BelongsTo→CashTransaction), paidBy(BelongsTo→User), payrollAdjustments(HasMany→PayrollAdjustment)

payroll_adjustments → PayrollAdjustment

id payroll_id(FK→payrolls) attendance_id(FK→attendances,null) created_by_id(FK→users) type(enum) amount(ubig) description(100) created_at updated_at deleted_at

  • Casts: type(PayrollAdjustmentType), amount(int)
  • Scopes: bonus(), deduction()
  • Relations: payroll(BelongsTo→Payroll), attendance(BelongsTo→Attendance), createdBy(BelongsTo→User)

leave_requests → LeaveRequest

id employee_id(FK→employees) verified_by_id(FK→users,null) start_date(date) end_date(date) total_days(uint) status(enum,default:pending) verified_at(datetime,null) created_at updated_at deleted_at

  • Casts: status(LeaveRequestStatus), start_date(date:Y-m-d), end_date(date:Y-m-d), total_days(int), verified_at(datetime)
  • Scopes: approved(), cancelled(), pending(), rejected()
  • Relations: employee(BelongsTo→Employee), verifiedBy(BelongsTo→User)

Sales

orders → Order

id customer_id(FK→customers,null) marketing_id(FK→users,null) cash_transaction_id(FK→cash_transactions,unique,null) created_by_id(FK→users) order_number(30,unique) channel(enum) price_type(enum) status(enum,default:pending) payment_type(enum,default:cash) tiktok_order_id(100,null) shopee_order_id(100,null) subtotal(ubig) discount(ubig,default:0) nego_price(ubig,null) total_amount(ubig) cogs(ubig,default:0) notes(text,null) created_at updated_at deleted_at

  • Casts: channel(OrderChannel), price_type(PriceType), status(OrderStatus), payment_type(PaymentType), subtotal(int), discount(int), nego_price(int), total_amount(int), cogs(int)
  • Scopes: cancelled(), cash(), completed(), pending(), processing(), qris(), refunded(), retail(), shopee(), store(), tiktok(), transfer(), wholesale()
  • Relations: cashTransaction(BelongsTo→CashTransaction), createdBy(BelongsTo→User), customer(BelongsTo→Customer), marketing(BelongsTo→User), orderItems(HasMany→OrderItem)

order_items → OrderItem

id order_id(FK→orders,null) user_id(FK→users,null) product_variant_id(FK→product_variants) stock_quality(enum,default:good) quantity(uint) unit_price(ubig) subtotal(ubig) created_at updated_at deleted_at

  • Casts: stock_quality(ProductStockQuality), quantity(int), unit_price(int), subtotal(int)
  • Scopes: good(), reject()
  • Relations: order(BelongsTo→Order), productVariant(BelongsTo→ProductVariant), user(BelongsTo→User)

rejections → Rejection

id rejectable_type(string,null,morph) rejectable_id(ubig,null,morph) rejected_by_id(FK→users) reason(500) created_at updated_at deleted_at

  • Relations: rejectable(MorphTo), rejectedBy(BelongsTo→User)

Production

cuttings → Cutting

id created_by_id(FK→users) status(enum,default:in_progress) description(100,null) total_material_cost(ubig,null) cost_per_unit(ubig,null) created_at updated_at deleted_at

  • Casts: status(CuttingStatus), total_material_cost(int), cost_per_unit(int)
  • Scopes: cancelled(), completed(), inProgress()
  • Relations: createdBy(BelongsTo→User), cuttingMaterialCombinations(HasMany→CuttingMaterialCombination), cuttingMaterials(HasMany→CuttingMaterial), cuttingResults(HasMany→CuttingResult)

cutting_material_combinations → CuttingMaterialCombination

id user_id(FK→users,null) cutting_id(FK→cuttings,null) material_result(int,null) created_at updated_at deleted_at

  • Casts: material_result(int)
  • Accessor: formatted_material_result → 'X.XXX'
  • Relations: cutting(BelongsTo→Cutting), cuttingMaterials(HasMany→CuttingMaterial,combination_id), user(BelongsTo→User)

cutting_materials → CuttingMaterial

id user_id(FK→users,null) cutting_id(FK→cuttings,null) raw_material_price_id(FK→raw_material_prices) combination_id(FK→cutting_material_combinations,null) material_usage(int) material_result(int,null) created_at updated_at deleted_at

  • Casts: material_usage(int), material_result(int)
  • Accessor: formatted_material_result → 'X.XXX', formatted_material_usage → 'X.XXX'
  • Relations: cutting(BelongsTo→Cutting), rawMaterialPrice(BelongsTo→RawMaterialPrice), combination(BelongsTo→CuttingMaterialCombination), user(BelongsTo→User)

cutting_results → CuttingResult

id user_id(FK→users,null) cutting_id(FK→cuttings,null) product_name(255,null) cutting_result(uint,null) sample(uint,null) original_outside_sample(uint,null) created_at updated_at deleted_at

  • Casts: cutting_result(int), sample(int), original_outside_sample(int)
  • Accessor: formatted_cutting_result → 'X.XXX', formatted_original_outside_sample → 'X.XXX', formatted_sample → 'X.XXX'
  • Relations: cutting(BelongsTo→Cutting), user(BelongsTo→User)

Inventory

purchases → Purchase

id supplier_id(FK→suppliers) created_by_id(FK→users) subtotal(ubig) discount(ubig,default:0) shipping_cost(ubig,default:0) total(ubig) notes(100,null) created_at updated_at deleted_at

  • Casts: subtotal(int), discount(int), shipping_cost(int), total(int)
  • Relations: createdBy(BelongsTo→User), supplier(BelongsTo→Supplier), purchaseItems(HasMany→PurchaseItem)

purchase_items → PurchaseItem

id purchase_id(FK→purchases,null) user_id(FK→users,null) raw_material_price_id(FK→raw_material_prices) quantity(uint) unit_price(ubig) subtotal(ubig) created_at updated_at deleted_at

  • Casts: quantity(int), unit_price(int), subtotal(int)
  • Relations: purchase(BelongsTo→Purchase), rawMaterialPrice(BelongsTo→RawMaterialPrice,withTrashed), user(BelongsTo→User)

restocks → Restock

id created_by_id(FK→users) total(ubig) notes(100,null) stock_type(enum,default:good) created_at updated_at deleted_at

  • Casts: stock_type(ProductStockQuality), total(int)
  • Scopes: good(), reject()
  • Relations: createdBy(BelongsTo→User), restockItems(HasMany→RestockItem)

restock_items → RestockItem

id restock_id(FK→restocks,null) user_id(FK→users,null) product_variant_id(FK→product_variants) quantity(int) unit_price(ubig) subtotal(ubig) created_at updated_at deleted_at

  • Casts: quantity(int), unit_price(int), subtotal(int)
  • Relations: restock(BelongsTo→Restock), productVariant(BelongsTo→ProductVariant), user(BelongsTo→User)

stok_opnames → StokOpname

id created_by_id(FK→users) verified_by_id(FK→users,null) opname_date(date) status(enum,default:draft) notes(text,null) verification_notes(text,null) created_at updated_at deleted_at

  • Casts: status(StokOpnameStatus), opname_date(date:Y-m-d)
  • Scopes: cancelled(), completed(), draft(), inProgress(), verified()
  • Relations: createdBy(BelongsTo→User), verifiedBy(BelongsTo→User), stokOpnameItems(HasMany→StokOpnameItem)

stok_opname_items → StokOpnameItem

id stok_opname_id(FK→stok_opnames) product_variant_id(FK→product_variants) stock_quality(enum,default:good) system_stock(uint,default:0) physical_stock(uint,default:0) difference(int,default:0) notes(text,null) created_at updated_at

  • No soft deletes
  • Casts: stock_quality(ProductStockQuality), system_stock(int), physical_stock(int), difference(int)
  • Scopes: good(), reject()
  • Relations: stokOpname(BelongsTo→StokOpname), productVariant(BelongsTo→ProductVariant)

retail_stock_histories → RetailStockHistory

id product_variant_id(FK→product_variants) user_id(FK→users) quantity(uint) stock_before(uint) retail_stock_before(uint) stock_after(uint) retail_stock_after(uint) notes(255,null) created_at

  • No soft deletes, no updated_at
  • $timestamps = false
  • Casts: quantity(int), stock_before(int), retail_stock_before(int), stock_after(int), retail_stock_after(int)
  • Accessor: formatted_quantity → 'X.XXX', formatted_retail_stock_before → 'X.XXX', formatted_retail_stock_after → 'X.XXX', formatted_stock_before → 'X.XXX', formatted_stock_after → 'X.XXX'
  • Relations: productVariant(BelongsTo→ProductVariant), user(BelongsTo→User)

stock_mutations → StockMutation

id user_id(FK→users) stockable_type(string) stockable_id(ubig) type(string) source_type(string,null) source_id(ubig,null) quantity(int) stock_before(int) stock_after(int) stock_quality(string,null) description(string,null) created_at updated_at

  • No soft deletes
  • Casts: quantity(int), stock_before(int), stock_after(int)
  • Accessor: formatted_quantity → 'X.XXX', formatted_stock_after → 'X.XXX', formatted_stock_before → 'X.XXX'
  • Relations: stockable(MorphTo), source(MorphTo), user(BelongsTo→User)

Settings

system_configurations → SystemConfiguration

id created_at updated_at

  • Singleton table

homepage_configurations → HomepageConfiguration

id created_at updated_at

  • Singleton table

settings (laravel-settings)

id group(string) name(string) locked(bool,default:false) payload(json) created_at updated_at

  • UNIQUE(group, name)

Enums

Enum Values Used In
CashTransactionType deposit, expense, transfer, withdrawal cash_transactions.type
CuttingStatus in_progress, completed, cancelled cuttings.status
EmployeeAdvanceStatus pending, disbursed, partial, repaid, rejected employee_advances.status
EmploymentStatus full_time, part_time, contract, internship, resigned employees.employment_status
Gender male, female user_profiles.gender
LeaveRequestStatus pending, approved, rejected, cancelled leave_requests.status
Modules Permission module names
OrderChannel store, shopee, tiktok orders.channel
OrderStatus pending, processing, completed, cancelled, refunded orders.status
PaymentType cash, transfer, qris orders.payment_type
PayrollAdjustmentType bonus, deduction payroll_adjustments.type
PayrollPeriodStatus open, closed payroll_periods.status
PayrollStatus unpaid, paid, cancelled payrolls.status
Permission Permission action names
PriceType retail, wholesale, capital product_prices.type, orders.price_type
ProductStatus active, draft, inactive, pending, rejected products.status
ProductStockQuality good, reject order_items.stock_quality, restocks.stock_type, stok_opname_items.stock_quality
RawMaterialUnit kg, meter, yard raw_materials.unit
Role Role names
StokOpnameStatus draft, in_progress, completed, verified, cancelled stok_opnames.status

Service Concerns

Trait Methods Used By
HandlesCashTransactions getCashAccount(), creditCash(), debitCash() CashAccountService, ExpenseService, EmployeeAdvanceService, PayrollPeriodService
HasStockAdjustment adjustStock(), adjustVariantStock(), applyStock(), reverseStock() TransactionService, RestockService
RegistersMedia registerMedia(), syncPhoto() CashAccountService, CuttingService, ExpenseService, PurchaseService, RestockService, TransactionService

Form Request Validation Rules

Validasi harus SESUAI dengan DB schema (type + max length).

Master

Request Field Rules DB Match
CategoryRequest name required, string, max:50, unique:categories,name varchar(50)
CustomerRequest name required, string, max:200, unique:customers,name varchar(200)
CustomerRequest phone_number nullable, string, max:20 varchar(20)
CustomerRequest address nullable, string text
SupplierRequest name required, string, max:200, unique:suppliers,name varchar(200)
SupplierRequest phone_number nullable, string, max:20 varchar(20)
RawMaterialRequest name required, string, max:200 varchar(200)
RawMaterialRequest unit required, in:kg,meter,yard enum
RawMaterialVariantRequest variant required, string, max:200 varchar(200)
RawMaterialVariantRequest price required, integer, min:0 uint
ProductRequest name required, string, max:200 varchar(200)
ProductRequest is_featured nullable, boolean bool
ProductVariantRequest name required, string, max:200 varchar(200)

Finance

Request Field Rules DB Match
CashAccountRequest name required, string, max:200, unique:cash_accounts,name varchar(200)
CashTransactionRequest amount required, integer, min:1 ubig
CashTransactionRequest description required, string, max:100 varchar(100)
ExpenseRequest amount required, integer, min:1 ubig
ExpenseRequest description required, string, max:100 varchar(100)
EmployeeAdvanceRequest amount required, integer, min:1 ubig
EmployeeAdvanceRequest description required, string, max:100 varchar(100)
EmployeeAdvanceRequest due_date required, date, after_or_equal:today date
EmployeeAdvancePaymentRequest amount required, integer, min:1 ubig
EmployeeAdvancePaymentRequest description nullable, string, max:100 varchar(100) nullable
PayrollAdjustmentRequest type required, in:bonus,deduction enum
PayrollAdjustmentRequest amount required, integer, min:1 ubig
PayrollAdjustmentRequest description required, string, max:100 varchar(100)

HR

Request Field Rules DB Match
EmployeeRequest email required, email, max:100, unique:users,email varchar(100)
EmployeeRequest username required, string, max:20, alpha_dash, unique:users,username varchar(20)
EmployeeRequest full_name required, string, max:200 varchar(200)
EmployeeRequest phone_number nullable, string, max:20 varchar(20)
EmployeeRequest gender nullable, in:male,female enum
EmployeeRequest base_salary required, integer, min:0 uint
AttendanceRequest latitude required, numeric, min:-90, max:90 decimal(10,7)
AttendanceRequest longitude required, numeric, min:-180, max:180 decimal(10,7)
LeaveRequestRequest start_date required, date, after:today date
LeaveRequestRequest end_date required, date, after_or_equal:start_date date

Sales

Request Field Rules DB Match
TransactionRequest channel required, in:store,shopee,tiktok enum
TransactionRequest price_type required, in:retail,wholesale enum
TransactionRequest payment_type required, in:cash,transfer,qris enum
TransactionRequest tiktok_order_id nullable, string, max:100 varchar(100)
TransactionRequest shopee_order_id nullable, string, max:100 varchar(100)
TransactionRequest notes nullable, string, max:100 text (UI limit)

Production

Request Field Rules DB Match
CuttingRequest description nullable, string, max:100 varchar(100)
CuttingRequest product_name required, string, max:255 varchar(255)
CuttingRequest cutting_result required, integer, min:1 uint
CuttingRequest sample required, integer uint
CuttingRequest original_outside_sample required, integer uint

Inventory

Request Field Rules DB Match
PurchaseRequest supplier_id required, integer, exists:suppliers,id FK
PurchaseRequest notes nullable, string, max:100 varchar(100)
RestockRequest stock_type required, in:good,reject enum
RestockRequest notes nullable, string, max:100 varchar(100)