add invoice pdf
This commit is contained in:
@@ -441,7 +441,7 @@
|
|||||||
"invoice.payment_attachment":"Payment attachment",
|
"invoice.payment_attachment":"Payment attachment",
|
||||||
"invoice.box_info":"Cartons",
|
"invoice.box_info":"Cartons",
|
||||||
"invoice.cargo_table":"Cargo table",
|
"invoice.cargo_table":"Cargo table",
|
||||||
"invoice.btn_create":"Create invoice",
|
"invoice.issue.btn":"Issue invoice",
|
||||||
"invoice.btn_save":"Save invoice",
|
"invoice.btn_save":"Save invoice",
|
||||||
"invoice.btn_payment_receipt":"Attachment payment receipt",
|
"invoice.btn_payment_receipt":"Attachment payment receipt",
|
||||||
"invoice.description": "Description",
|
"invoice.description": "Description",
|
||||||
@@ -458,8 +458,9 @@
|
|||||||
"invoice.pdf": "Invoice PDF",
|
"invoice.pdf": "Invoice PDF",
|
||||||
"invoice.total_custom_fee":"Total custom fee",
|
"invoice.total_custom_fee":"Total custom fee",
|
||||||
"invoice.shipment_weight":"Shipment weight",
|
"invoice.shipment_weight":"Shipment weight",
|
||||||
"invoice.popupmenu.pending":"Pending",
|
"invoice.popupmenu.issused":"Issused",
|
||||||
"invoice.popupmenu.paid":"Paid",
|
"invoice.popupmenu.paid":"Paid",
|
||||||
|
"invoice.popupmenu.cancel":"Canceled",
|
||||||
"invoice.shipment.title":"Select FCS shipment",
|
"invoice.shipment.title":"Select FCS shipment",
|
||||||
"invoice.customer.title":"Select Customer",
|
"invoice.customer.title":"Select Customer",
|
||||||
"invoice.add.custom.fee.menu":"Custom fee",
|
"invoice.add.custom.fee.menu":"Custom fee",
|
||||||
@@ -468,6 +469,8 @@
|
|||||||
"invoice.shipment.handling.fee.title":"Select shipment",
|
"invoice.shipment.handling.fee.title":"Select shipment",
|
||||||
"invoice.shipment.number":"Shipment number",
|
"invoice.shipment.number":"Shipment number",
|
||||||
"invoice.shipment.discount.title":"Select discount",
|
"invoice.shipment.discount.title":"Select discount",
|
||||||
|
"invoice.cancel.btn":"Cancel",
|
||||||
|
"invoice.cancel.confirm":"Cancel invoice?",
|
||||||
"Invoices End ================================================================":"",
|
"Invoices End ================================================================":"",
|
||||||
|
|
||||||
"Discount Start ================================================================":"",
|
"Discount Start ================================================================":"",
|
||||||
|
|||||||
@@ -441,7 +441,8 @@
|
|||||||
"invoice.payment_attachment":"ပေးချေပြီးဖိုင်များ",
|
"invoice.payment_attachment":"ပေးချေပြီးဖိုင်များ",
|
||||||
"invoice.box_info":"Cartons",
|
"invoice.box_info":"Cartons",
|
||||||
"invoice.cargo_table":"ကုန်ပစ္စည်းဇယား",
|
"invoice.cargo_table":"ကုန်ပစ္စည်းဇယား",
|
||||||
"invoice.btn_create":"ငွေတောင်းခံလွှာ ပြုလုပ်ရန်",
|
"invoice.issue.btn":"ငွေတောင်းခံလွှာ ထုတ်မည်",
|
||||||
|
|
||||||
"invoice.btn_save":"ငွေတောင်းခံလွှာ သိမ်းရန်",
|
"invoice.btn_save":"ငွေတောင်းခံလွှာ သိမ်းရန်",
|
||||||
"invoice.btn_payment_receipt":"ငွေလက်ခံဖြတ်ပိုင်း ထည့်ရန်",
|
"invoice.btn_payment_receipt":"ငွေလက်ခံဖြတ်ပိုင်း ထည့်ရန်",
|
||||||
"invoice.box.cargo_type": "ကုန်ပစ္စည်းအမျိုးအစားများ",
|
"invoice.box.cargo_type": "ကုန်ပစ္စည်းအမျိုးအစားများ",
|
||||||
@@ -458,8 +459,9 @@
|
|||||||
"invoice.pdf": "Invoice PDF",
|
"invoice.pdf": "Invoice PDF",
|
||||||
"invoice.total_custom_fee":"အခွန်စုစုပေါင်း",
|
"invoice.total_custom_fee":"အခွန်စုစုပေါင်း",
|
||||||
"invoice.shipment_weight":"Shipment weight",
|
"invoice.shipment_weight":"Shipment weight",
|
||||||
"invoice.popupmenu.pending":"Pending",
|
"invoice.popupmenu.issused":"Issused",
|
||||||
"invoice.popupmenu.paid":"Paid",
|
"invoice.popupmenu.paid":"Paid",
|
||||||
|
"invoice.popupmenu.cancel":"Canceled",
|
||||||
"invoice.shipment.title":"Select FCS shipment",
|
"invoice.shipment.title":"Select FCS shipment",
|
||||||
"invoice.customer.title":"Select Customer",
|
"invoice.customer.title":"Select Customer",
|
||||||
"invoice.add.custom.fee.menu":"Custom fee",
|
"invoice.add.custom.fee.menu":"Custom fee",
|
||||||
@@ -468,6 +470,8 @@
|
|||||||
"invoice.shipment.number":"Shipment number",
|
"invoice.shipment.number":"Shipment number",
|
||||||
"invoice.shipment.handling.fee.title":"Select shipment",
|
"invoice.shipment.handling.fee.title":"Select shipment",
|
||||||
"invoice.shipment.discount.title":"Select discount",
|
"invoice.shipment.discount.title":"Select discount",
|
||||||
|
"invoice.cancel.btn":"Cancel",
|
||||||
|
"invoice.cancel.confirm":"Cancel invoice?",
|
||||||
"Invoices End ================================================================":"",
|
"Invoices End ================================================================":"",
|
||||||
|
|
||||||
"Discount Start ================================================================":"",
|
"Discount Start ================================================================":"",
|
||||||
|
|||||||
25
lib/data/provider/invoice_data_provider.dart
Normal file
25
lib/data/provider/invoice_data_provider.dart
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import 'package:fcs/domain/entities/invoice.dart';
|
||||||
|
import 'package:fcs/helpers/api_helper.dart';
|
||||||
|
import 'package:fcs/helpers/firebase_helper.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
class InvoiceDataProvider {
|
||||||
|
final log = Logger('InvoiceDataProvider');
|
||||||
|
static final InvoiceDataProvider instance = InvoiceDataProvider._();
|
||||||
|
InvoiceDataProvider._();
|
||||||
|
|
||||||
|
Future<void> createInvoice(Invoice invoice) async {
|
||||||
|
return await requestAPI("/invoices", "POST",
|
||||||
|
payload: invoice.toMap(), token: await getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateInvoice(Invoice invoice) async {
|
||||||
|
return await requestAPI("/invoices", "PUT",
|
||||||
|
payload: invoice.toMap(), token: await getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> cancelInvoice(Invoice invoice) async {
|
||||||
|
return await requestAPI("/invoices/cancel", "PUT",
|
||||||
|
payload: {"id": invoice.id}, token: await getToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
34
lib/data/services/invoice_imp.dart
Normal file
34
lib/data/services/invoice_imp.dart
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import 'package:fcs/data/provider/invoice_data_provider.dart';
|
||||||
|
import 'package:fcs/data/provider/shipment_data_provider.dart';
|
||||||
|
import 'package:fcs/data/services/shipment_service.dart';
|
||||||
|
import 'package:fcs/domain/entities/connectivity.dart';
|
||||||
|
import 'package:fcs/domain/entities/invoice.dart';
|
||||||
|
import 'package:fcs/domain/entities/shipment.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'invoice_service.dart';
|
||||||
|
|
||||||
|
class InvoiceServiceImp implements InvoiceService {
|
||||||
|
InvoiceServiceImp({
|
||||||
|
@required this.invoiceDataProvider,
|
||||||
|
@required this.connectivity,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Connectivity connectivity;
|
||||||
|
final InvoiceDataProvider invoiceDataProvider;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> cancelInvoice(Invoice invoice) {
|
||||||
|
return invoiceDataProvider.cancelInvoice(invoice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> createInvoice(Invoice invoice) {
|
||||||
|
return invoiceDataProvider.createInvoice(invoice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> updateInvoice(Invoice invoice) {
|
||||||
|
return invoiceDataProvider.updateInvoice(invoice);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
lib/data/services/invoice_service.dart
Normal file
8
lib/data/services/invoice_service.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:fcs/domain/entities/invoice.dart';
|
||||||
|
import 'package:fcs/domain/entities/shipment.dart';
|
||||||
|
|
||||||
|
abstract class InvoiceService {
|
||||||
|
Future<void> createInvoice(Invoice invoice);
|
||||||
|
Future<void> updateInvoice(Invoice invoice);
|
||||||
|
Future<void> cancelInvoice(Invoice invoice);
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import 'package:fcs/data/provider/carton_data_provider.dart';
|
|||||||
import 'package:fcs/data/provider/common_data_provider.dart';
|
import 'package:fcs/data/provider/common_data_provider.dart';
|
||||||
import 'package:fcs/data/provider/delivery_address_data_provider.dart';
|
import 'package:fcs/data/provider/delivery_address_data_provider.dart';
|
||||||
import 'package:fcs/data/provider/fcs_shipment_data_provider.dart';
|
import 'package:fcs/data/provider/fcs_shipment_data_provider.dart';
|
||||||
|
import 'package:fcs/data/provider/invoice_data_provider.dart';
|
||||||
import 'package:fcs/data/provider/package_data_provider.dart';
|
import 'package:fcs/data/provider/package_data_provider.dart';
|
||||||
import 'package:fcs/data/provider/rate_data_provider.dart';
|
import 'package:fcs/data/provider/rate_data_provider.dart';
|
||||||
import 'package:fcs/data/provider/shipment_data_provider.dart';
|
import 'package:fcs/data/provider/shipment_data_provider.dart';
|
||||||
@@ -13,6 +14,8 @@ import 'package:fcs/data/services/delivery_address_imp.dart';
|
|||||||
import 'package:fcs/data/services/delivery_address_service.dart';
|
import 'package:fcs/data/services/delivery_address_service.dart';
|
||||||
import 'package:fcs/data/services/fcs_shipment_imp.dart';
|
import 'package:fcs/data/services/fcs_shipment_imp.dart';
|
||||||
import 'package:fcs/data/services/fcs_shipment_service.dart';
|
import 'package:fcs/data/services/fcs_shipment_service.dart';
|
||||||
|
import 'package:fcs/data/services/invoice_imp.dart';
|
||||||
|
import 'package:fcs/data/services/invoice_service.dart';
|
||||||
import 'package:fcs/data/services/rate_imp.dart';
|
import 'package:fcs/data/services/rate_imp.dart';
|
||||||
import 'package:fcs/data/services/rate_service.dart';
|
import 'package:fcs/data/services/rate_service.dart';
|
||||||
import 'package:fcs/data/services/shipment_imp.dart';
|
import 'package:fcs/data/services/shipment_imp.dart';
|
||||||
@@ -42,6 +45,7 @@ class Services {
|
|||||||
RateService _rateService;
|
RateService _rateService;
|
||||||
ShipmentService _shipmentService;
|
ShipmentService _shipmentService;
|
||||||
CartonService _cartonService;
|
CartonService _cartonService;
|
||||||
|
InvoiceService _invoiceService;
|
||||||
Services._() {
|
Services._() {
|
||||||
_authService = AuthServiceImp(
|
_authService = AuthServiceImp(
|
||||||
authFb: AuthFb.instance,
|
authFb: AuthFb.instance,
|
||||||
@@ -65,6 +69,8 @@ class Services {
|
|||||||
connectivity: null);
|
connectivity: null);
|
||||||
_cartonService = CartonServiceImp(
|
_cartonService = CartonServiceImp(
|
||||||
cartonDataProvider: CartonDataProvider.instance, connectivity: null);
|
cartonDataProvider: CartonDataProvider.instance, connectivity: null);
|
||||||
|
_invoiceService = InvoiceServiceImp(
|
||||||
|
invoiceDataProvider: InvoiceDataProvider.instance, connectivity: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthService get authService => _authService;
|
AuthService get authService => _authService;
|
||||||
@@ -77,4 +83,5 @@ class Services {
|
|||||||
RateService get rateService => _rateService;
|
RateService get rateService => _rateService;
|
||||||
ShipmentService get shipmentService => _shipmentService;
|
ShipmentService get shipmentService => _shipmentService;
|
||||||
CartonService get cartonService => _cartonService;
|
CartonService get cartonService => _cartonService;
|
||||||
|
InvoiceService get invoiceService => _invoiceService;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,3 +91,9 @@ const shipment_pickuped_status = "pickuped";
|
|||||||
const shipment_packed_status = "packed";
|
const shipment_packed_status = "packed";
|
||||||
const shipment_shipped_status = "shipped";
|
const shipment_shipped_status = "shipped";
|
||||||
const shipment_delivered_status = "delivered";
|
const shipment_delivered_status = "delivered";
|
||||||
|
|
||||||
|
// invoice status
|
||||||
|
const invoice_issued_status = "issued";
|
||||||
|
const invoice_saved_status = "saved";
|
||||||
|
const invoice_cancel_status = "canceled";
|
||||||
|
const invoice_paid_status = "paid";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class CargoType {
|
|||||||
double rate;
|
double rate;
|
||||||
double weight;
|
double weight;
|
||||||
|
|
||||||
double amount;
|
double get calAmount => (calRate ?? 0) * (calWeight ?? 0);
|
||||||
|
|
||||||
double calRate;
|
double calRate;
|
||||||
double calWeight;
|
double calWeight;
|
||||||
@@ -16,9 +16,16 @@ class CargoType {
|
|||||||
rate: map['rate']?.toDouble() ?? 0,
|
rate: map['rate']?.toDouble() ?? 0,
|
||||||
weight: map['weight']?.toDouble() ?? 0,
|
weight: map['weight']?.toDouble() ?? 0,
|
||||||
calWeight: map['cal_weight']?.toDouble() ?? 0,
|
calWeight: map['cal_weight']?.toDouble() ?? 0,
|
||||||
|
calRate: map['cal_rate']?.toDouble() ?? 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
CargoType({this.id, this.name, this.rate, this.weight, this.calWeight});
|
CargoType(
|
||||||
|
{this.id,
|
||||||
|
this.name,
|
||||||
|
this.rate,
|
||||||
|
this.weight,
|
||||||
|
this.calWeight,
|
||||||
|
this.calRate});
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return {
|
return {
|
||||||
@@ -27,6 +34,7 @@ class CargoType {
|
|||||||
'rate': rate,
|
'rate': rate,
|
||||||
'weight': weight,
|
'weight': weight,
|
||||||
'cal_weight': calWeight,
|
'cal_weight': calWeight,
|
||||||
|
'cal_rate': calRate,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ class Carton {
|
|||||||
'length': length,
|
'length': length,
|
||||||
'width': width,
|
'width': width,
|
||||||
'height': height,
|
'height': height,
|
||||||
'delivery_address': deliveryAddress.toMap(),
|
'delivery_address': deliveryAddress?.toMap(),
|
||||||
'carton_type': cartonType,
|
'carton_type': cartonType,
|
||||||
'mix_carton_id': mixCartonID,
|
'mix_carton_id': mixCartonID,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:fcs/domain/entities/cargo_type.dart';
|
import 'package:fcs/domain/entities/cargo_type.dart';
|
||||||
import 'package:fcs/domain/entities/carton.dart';
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
import 'package:fcs/domain/entities/custom_duty.dart';
|
import 'package:fcs/domain/entities/custom_duty.dart';
|
||||||
@@ -13,6 +14,7 @@ class Invoice {
|
|||||||
DateTime invoiceDate;
|
DateTime invoiceDate;
|
||||||
String fcsShipmentID;
|
String fcsShipmentID;
|
||||||
String userID;
|
String userID;
|
||||||
|
String fcsID;
|
||||||
String userName;
|
String userName;
|
||||||
String phoneNumber;
|
String phoneNumber;
|
||||||
String status;
|
String status;
|
||||||
@@ -28,20 +30,23 @@ class Invoice {
|
|||||||
List<Shipment> shipments;
|
List<Shipment> shipments;
|
||||||
Discount discount;
|
Discount discount;
|
||||||
PaymentMethod paymentMethod;
|
PaymentMethod paymentMethod;
|
||||||
|
String invoiceURL;
|
||||||
|
|
||||||
List<CargoType> getCargoTypes(Rate rate) {
|
List<CargoType> getCargoTypes(Rate rate) {
|
||||||
List<CargoType> cargoTypes = [];
|
if (cargoTypes != null) return cargoTypes;
|
||||||
|
|
||||||
|
List<CargoType> _cargoTypes = [];
|
||||||
double totalCalWeight = 0;
|
double totalCalWeight = 0;
|
||||||
cartons.forEach((carton) {
|
cartons.forEach((carton) {
|
||||||
if (carton.isChecked) {
|
if (carton.isChecked) {
|
||||||
var _cartonsTypes =
|
var _cartonsTypes =
|
||||||
carton.getCargoTypeForCalWeight(rate.volumetricRatio);
|
carton.getCargoTypeForCalWeight(rate.volumetricRatio);
|
||||||
_cartonsTypes.forEach((ct) {
|
_cartonsTypes.forEach((ct) {
|
||||||
if (cargoTypes.contains(ct)) {
|
if (_cargoTypes.contains(ct)) {
|
||||||
CargoType existing = cargoTypes.firstWhere((wc) => wc.id == ct.id);
|
CargoType existing = _cargoTypes.firstWhere((wc) => wc.id == ct.id);
|
||||||
existing.calWeight += ct.calWeight;
|
existing.calWeight += ct.calWeight;
|
||||||
} else {
|
} else {
|
||||||
cargoTypes.add(ct.clone());
|
_cargoTypes.add(ct.clone());
|
||||||
}
|
}
|
||||||
totalCalWeight += ct.calWeight;
|
totalCalWeight += ct.calWeight;
|
||||||
});
|
});
|
||||||
@@ -51,25 +56,23 @@ class Invoice {
|
|||||||
DiscountByWeight discountByWeight =
|
DiscountByWeight discountByWeight =
|
||||||
rate.getDiscountByWeight(totalCalWeight);
|
rate.getDiscountByWeight(totalCalWeight);
|
||||||
|
|
||||||
cargoTypes.forEach((e) {
|
_cargoTypes.forEach((e) {
|
||||||
double r =
|
double r =
|
||||||
e.rate - (discountByWeight != null ? discountByWeight.discount : 0);
|
e.rate - (discountByWeight != null ? discountByWeight.discount : 0);
|
||||||
double amount = e.calWeight * r;
|
|
||||||
e.calRate = r;
|
e.calRate = r;
|
||||||
e.amount = amount;
|
|
||||||
});
|
});
|
||||||
return cargoTypes;
|
return _cargoTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getTotal(Rate rate) {
|
double getTotal(Rate rate) {
|
||||||
List<CargoType> cargoTypes = getCargoTypes(rate);
|
List<CargoType> cargoTypes = getCargoTypes(rate);
|
||||||
var total = cargoTypes.fold(0.0, (p, c) => c.amount + p);
|
var total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p);
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getNetAmount(Rate rate) {
|
double getNetAmount(Rate rate) {
|
||||||
List<CargoType> cargoTypes = getCargoTypes(rate);
|
List<CargoType> cargoTypes = getCargoTypes(rate);
|
||||||
var total = cargoTypes.fold(0.0, (p, c) => c.amount + p);
|
var total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p);
|
||||||
total += getCustomFee();
|
total += getCustomFee();
|
||||||
total += getDeliveryFee();
|
total += getDeliveryFee();
|
||||||
total += getHandlingFee();
|
total += getHandlingFee();
|
||||||
@@ -78,7 +81,7 @@ class Invoice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double getHandlingFee() {
|
double getHandlingFee() {
|
||||||
return shipments?.where((sh) => sh.isSelected)?.fold(0, (p, s) {
|
return shipments?.where((sh) => sh.isSelected ?? false)?.fold(0, (p, s) {
|
||||||
return p + (s?.handlingFee ?? 0) - (s?.paidHandlingFee ?? 0);
|
return p + (s?.handlingFee ?? 0) - (s?.paidHandlingFee ?? 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -97,33 +100,65 @@ class Invoice {
|
|||||||
|
|
||||||
double getDiscount() => discount == null ? 0 : discount.amount;
|
double getDiscount() => discount == null ? 0 : discount.amount;
|
||||||
|
|
||||||
Invoice({
|
Invoice(
|
||||||
this.id,
|
{this.id,
|
||||||
this.invoiceNumber,
|
this.invoiceNumber,
|
||||||
this.invoiceDate,
|
this.invoiceDate,
|
||||||
this.userName,
|
this.fcsID,
|
||||||
this.phoneNumber,
|
this.userName,
|
||||||
this.amount,
|
this.phoneNumber,
|
||||||
this.discount,
|
this.amount,
|
||||||
this.status,
|
this.discount,
|
||||||
this.customDuties,
|
this.status,
|
||||||
this.cartons,
|
this.customDuties,
|
||||||
this.cargoTypes,
|
this.cartons,
|
||||||
this.handlingFee,
|
this.cargoTypes,
|
||||||
this.fcsShipmentID,
|
this.handlingFee,
|
||||||
this.shipments,
|
this.deliveryFee,
|
||||||
});
|
this.fcsShipmentID,
|
||||||
|
this.shipments,
|
||||||
|
this.invoiceURL,
|
||||||
|
this.paymentMethod});
|
||||||
|
|
||||||
factory Invoice.fromMap(Map<String, dynamic> map, String docID) {
|
factory Invoice.fromMap(Map<String, dynamic> map, String docID) {
|
||||||
|
var invd = (map['invoice_date'] as Timestamp);
|
||||||
|
var cargoTypesMaps =
|
||||||
|
List<Map<String, dynamic>>.from(map['cargo_types'] ?? []);
|
||||||
|
var cargoTypes =
|
||||||
|
cargoTypesMaps.map((e) => CargoType.fromMap(e, e["id"])).toList();
|
||||||
|
var customDutiesMap =
|
||||||
|
List<Map<String, dynamic>>.from(map['custom_duties'] ?? []);
|
||||||
|
var customDuties =
|
||||||
|
customDutiesMap.map((e) => CustomDuty.fromMap(e, e["id"])).toList();
|
||||||
|
var handlingShipmentsMap =
|
||||||
|
List<Map<String, dynamic>>.from(map['handling_fee_shipments'] ?? []);
|
||||||
|
var handingShipments =
|
||||||
|
handlingShipmentsMap.map((e) => Shipment.fromMap(e, e["id"])).toList();
|
||||||
|
var cartonsMap = List<Map<String, dynamic>>.from(map['cartons'] ?? []);
|
||||||
|
var cartons = cartonsMap.map((e) => Carton.fromMap(e, e["id"])).toList();
|
||||||
|
var paymentMethodMap = map['payment_method'];
|
||||||
|
var paymentMethod = paymentMethodMap != null
|
||||||
|
? PaymentMethod.fromMap(paymentMethodMap, paymentMethodMap['id'])
|
||||||
|
: null;
|
||||||
|
var discountMap = map['discount'];
|
||||||
|
var discount = Discount.fromMap(discountMap, discountMap['id']);
|
||||||
return Invoice(
|
return Invoice(
|
||||||
id: docID,
|
id: docID,
|
||||||
invoiceNumber: map['invoice_number'],
|
invoiceNumber: map['invoice_number'],
|
||||||
invoiceDate: map['invoice_date'],
|
invoiceDate: invd?.toDate(),
|
||||||
userName: map['user_name'],
|
userName: map['user_name'],
|
||||||
|
fcsID: map['fcs_id'],
|
||||||
phoneNumber: map['phone_number'],
|
phoneNumber: map['phone_number'],
|
||||||
amount: map['amount'],
|
amount: map['amount'],
|
||||||
status: map['status'],
|
status: map['status'],
|
||||||
discount: map['discount'],
|
cartons: cartons,
|
||||||
|
cargoTypes: cargoTypes,
|
||||||
|
shipments: handingShipments,
|
||||||
|
customDuties: customDuties,
|
||||||
|
deliveryFee: map['delivery_fee'],
|
||||||
|
invoiceURL: map['invoice_url'],
|
||||||
|
paymentMethod: paymentMethod,
|
||||||
|
discount: discount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,17 +166,24 @@ class Invoice {
|
|||||||
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
|
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
|
||||||
List _customDuties = customDuties?.map((c) => c.toMap())?.toList();
|
List _customDuties = customDuties?.map((c) => c.toMap())?.toList();
|
||||||
List _cartons = cartons?.map((c) => c.toMap())?.toList() ?? [];
|
List _cartons = cartons?.map((c) => c.toMap())?.toList() ?? [];
|
||||||
|
List _shipments = shipments?.map((s) => s.toMap())?.toList() ?? [];
|
||||||
return {
|
return {
|
||||||
"id": id,
|
"id": id,
|
||||||
"invoice_date": invoiceDate,
|
"invoice_date": invoiceDate?.toUtc()?.toIso8601String(),
|
||||||
"user_id": userID,
|
"user_id": userID,
|
||||||
|
"user_name": userName,
|
||||||
|
"invoice_number": invoiceNumber,
|
||||||
'fcs_shipment_id': fcsShipmentID,
|
'fcs_shipment_id': fcsShipmentID,
|
||||||
'cargo_types': _cargoTypes,
|
'cargo_types': _cargoTypes,
|
||||||
'custom_duties': _customDuties,
|
'custom_duties': _customDuties,
|
||||||
|
'handling_fee_shipments': _shipments,
|
||||||
'cartons': _cartons,
|
'cartons': _cartons,
|
||||||
'discount': discount?.toMap(),
|
'discount': discount?.toMap(),
|
||||||
|
'amount': amount,
|
||||||
'handling_fee': handlingFee,
|
'handling_fee': handlingFee,
|
||||||
'delivery_fee': deliveryFee,
|
'delivery_fee': deliveryFee,
|
||||||
|
'invoice_url': invoiceURL,
|
||||||
|
'payment_method': paymentMethod?.toMap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class Shipment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
List _boxes = boxes.map((l) => l.toMap()).toList();
|
List _boxes = boxes?.map((l) => l.toMap())?.toList() ?? [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"id": id,
|
"id": id,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
@@ -5,9 +6,11 @@ import 'package:device_info/device_info.dart';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:fcs/domain/vo/status.dart';
|
import 'package:fcs/domain/vo/status.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
import '../config.dart';
|
import '../config.dart';
|
||||||
import 'dev_info.dart';
|
import 'dev_info.dart';
|
||||||
|
import 'firebase_helper.dart';
|
||||||
|
|
||||||
final log = Logger('requestAPI');
|
final log = Logger('requestAPI');
|
||||||
|
|
||||||
@@ -146,3 +149,92 @@ Future<dynamic> requestDownloadPDFAPI(String path, method,
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef OnDownloadDone(File file);
|
||||||
|
// request makes http request
|
||||||
|
// if token is null
|
||||||
|
Future<dynamic> requestDownload(String path, method,
|
||||||
|
{dynamic payload,
|
||||||
|
String token,
|
||||||
|
String url,
|
||||||
|
String filePath,
|
||||||
|
OnDownloadDone onDownloadDone}) async {
|
||||||
|
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||||
|
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||||
|
String deviceName = "${androidInfo.model}(${androidInfo.id})";
|
||||||
|
log.info("device:${androidInfo.androidId},deviceName:$deviceName");
|
||||||
|
|
||||||
|
var bytes = utf8.encode(payload);
|
||||||
|
var base64Str = base64.encode(bytes);
|
||||||
|
String escapePayload = HtmlEscape().convert(base64Str);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String baseUrl = url == null ? Config.instance.apiURL : url;
|
||||||
|
log.info("Path:$baseUrl$path");
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
// var _downloadData = StringBuffer();
|
||||||
|
var request = await client.postUrl(Uri.parse("$baseUrl$path"));
|
||||||
|
request.headers.set("Project-ID", Config.instance.reportProjectID);
|
||||||
|
if (token != null) {
|
||||||
|
request.headers.set("Token", token);
|
||||||
|
}
|
||||||
|
if (androidInfo.androidId != null) {
|
||||||
|
request.headers.set("Device", androidInfo.androidId + ":" + deviceName);
|
||||||
|
}
|
||||||
|
request.headers
|
||||||
|
.set(HttpHeaders.contentTypeHeader, 'application/json; charset=utf-8');
|
||||||
|
request.headers.set("payload", escapePayload);
|
||||||
|
request.write(payload);
|
||||||
|
// request.write(escapePayload);
|
||||||
|
var response = await request.close();
|
||||||
|
print("headers:${response.headers}");
|
||||||
|
var _downloadData = List<int>();
|
||||||
|
var cd = response.headers.value("content-disposition");
|
||||||
|
String fileName = "download.csv";
|
||||||
|
if (cd != null && cd.contains("filename=")) {
|
||||||
|
fileName = cd.substring(cd.indexOf("=") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = filePath + "/" + fileName;
|
||||||
|
var fileSave = new File(filePath + "/" + fileName);
|
||||||
|
response.listen((d) => _downloadData.addAll(d), onDone: () async {
|
||||||
|
await fileSave.writeAsBytes(_downloadData);
|
||||||
|
if (onDownloadDone != null) {
|
||||||
|
onDownloadDone(fileSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
// final message = await OpenFile.open(file);
|
||||||
|
// log.info("Open file result:${message.message}");
|
||||||
|
// if (message.message != "done") {
|
||||||
|
// throw Exception(message.message);
|
||||||
|
// }
|
||||||
|
// await Share.file(fileName, fileName, _downloadData,
|
||||||
|
// downloadType == DownloadType.CSV ? "text/csv" : "application/pdf");
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
e.toString();
|
||||||
|
log.warning("path:$path, api:$e");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<File> downloadPDF(
|
||||||
|
String templateName, Map<String, dynamic> values) async {
|
||||||
|
final completer = Completer<File>();
|
||||||
|
|
||||||
|
final directory = await getApplicationSupportDirectory();
|
||||||
|
String path = ('${directory.path}');
|
||||||
|
log.info("download file path:$path");
|
||||||
|
|
||||||
|
var data = {"template_name": templateName, "data": values};
|
||||||
|
print("payload:$data");
|
||||||
|
|
||||||
|
await requestDownload("/api/pdf", "POST",
|
||||||
|
filePath: path,
|
||||||
|
url: Config.instance.reportURL,
|
||||||
|
token: await getToken(),
|
||||||
|
payload: jsonEncode(data), onDownloadDone: (f) async {
|
||||||
|
completer.complete(f);
|
||||||
|
});
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|||||||
12
lib/helpers/cache_mgr.dart
Normal file
12
lib/helpers/cache_mgr.dart
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
|
|
||||||
|
class PdfCacheMgr {
|
||||||
|
static const key = 'pdfs';
|
||||||
|
static CacheManager pdfs = CacheManager(
|
||||||
|
Config(
|
||||||
|
key,
|
||||||
|
stalePeriod: const Duration(days: 7),
|
||||||
|
maxNrOfCacheObjects: 20,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -162,6 +162,18 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_loadMixCartons() async {
|
||||||
|
if (_fcsShipment == null || _fcsShipment.id == null) return;
|
||||||
|
if (_selectedCartonType != carton_small_bag) return;
|
||||||
|
|
||||||
|
CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false);
|
||||||
|
List<Carton> cartons =
|
||||||
|
await cartonModel.getMixCartonsByFcsShipment(_fcsShipment.id);
|
||||||
|
setState(() {
|
||||||
|
_mixCartons = cartons;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_calShipmentWeight() {
|
_calShipmentWeight() {
|
||||||
double l = double.parse(_lengthController.text, (s) => 0);
|
double l = double.parse(_lengthController.text, (s) => 0);
|
||||||
double w = double.parse(_widthController.text, (s) => 0);
|
double w = double.parse(_widthController.text, (s) => 0);
|
||||||
@@ -196,6 +208,7 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_fcsShipment = v;
|
_fcsShipment = v;
|
||||||
});
|
});
|
||||||
|
_loadMixCartons();
|
||||||
},
|
},
|
||||||
labelKey: "shipment.pack.fcs.shipment",
|
labelKey: "shipment.pack.fcs.shipment",
|
||||||
iconData: Ionicons.ios_airplane,
|
iconData: Ionicons.ios_airplane,
|
||||||
@@ -291,7 +304,6 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
values: boxModel.cartonTypes,
|
values: boxModel.cartonTypes,
|
||||||
selectedValue: _selectedCartonType,
|
selectedValue: _selectedCartonType,
|
||||||
callback: (v) {
|
callback: (v) {
|
||||||
print(v);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedCartonType = v;
|
_selectedCartonType = v;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import 'package:fcs/pages/widgets/my_data_table.dart';
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class InvoiceDiscountTable extends StatelessWidget {
|
class InvoiceDiscountList extends StatelessWidget {
|
||||||
final List<Discount> discounts;
|
final List<Discount> discounts;
|
||||||
|
|
||||||
const InvoiceDiscountTable({
|
const InvoiceDiscountList({
|
||||||
Key key,
|
Key key,
|
||||||
this.discounts,
|
this.discounts,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:fcs/domain/entities/cargo_type.dart';
|
||||||
import 'package:fcs/domain/entities/carton.dart';
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
import 'package:fcs/domain/entities/custom_duty.dart';
|
import 'package:fcs/domain/entities/custom_duty.dart';
|
||||||
import 'package:fcs/domain/entities/discount.dart';
|
import 'package:fcs/domain/entities/discount.dart';
|
||||||
@@ -8,12 +9,12 @@ import 'package:fcs/domain/entities/shipment.dart';
|
|||||||
import 'package:fcs/domain/entities/user.dart';
|
import 'package:fcs/domain/entities/user.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/carton/model/carton_model.dart';
|
import 'package:fcs/pages/carton/model/carton_model.dart';
|
||||||
import 'package:fcs/pages/discount/discount_list.dart';
|
|
||||||
import 'package:fcs/pages/discount/model/discount_model.dart';
|
import 'package:fcs/pages/discount/model/discount_model.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_discount_table.dart';
|
import 'package:fcs/pages/invoice/editor/invoice_carton_table.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_shipment_table.dart';
|
import 'package:fcs/pages/invoice/editor/invoice_discount_list.dart';
|
||||||
|
import 'package:fcs/pages/invoice/editor/invoice_handling_fee_list.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_table.dart';
|
import 'package:fcs/pages/invoice/invoice_table.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_carton_table.dart';
|
import 'package:fcs/pages/invoice/model/invoice_model.dart';
|
||||||
import 'package:fcs/pages/main/model/main_model.dart';
|
import 'package:fcs/pages/main/model/main_model.dart';
|
||||||
import 'package:fcs/pages/main/util.dart';
|
import 'package:fcs/pages/main/util.dart';
|
||||||
import 'package:fcs/pages/payment_methods/model/payment_method_model.dart';
|
import 'package:fcs/pages/payment_methods/model/payment_method_model.dart';
|
||||||
@@ -22,12 +23,11 @@ import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
|
|||||||
import 'package:fcs/pages/shipment/model/shipment_model.dart';
|
import 'package:fcs/pages/shipment/model/shipment_model.dart';
|
||||||
import 'package:fcs/pages/widgets/display_text.dart';
|
import 'package:fcs/pages/widgets/display_text.dart';
|
||||||
import 'package:fcs/pages/widgets/fcs_icons.dart';
|
import 'package:fcs/pages/widgets/fcs_icons.dart';
|
||||||
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
|
import 'package:fcs/pages/widgets/local_button.dart';
|
||||||
import 'package:fcs/pages/widgets/local_dropdown.dart';
|
import 'package:fcs/pages/widgets/local_dropdown.dart';
|
||||||
import 'package:fcs/pages/widgets/local_popup_menu_button.dart';
|
import 'package:fcs/pages/widgets/local_popup_menu_button.dart';
|
||||||
import 'package:fcs/pages/widgets/local_popupmenu.dart';
|
import 'package:fcs/pages/widgets/local_popupmenu.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
import 'package:fcs/pages/widgets/local_title.dart';
|
|
||||||
import 'package:fcs/pages/widgets/progress.dart';
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -36,8 +36,6 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'invoice_custom_table.dart';
|
|
||||||
|
|
||||||
class InvoiceEditor extends StatefulWidget {
|
class InvoiceEditor extends StatefulWidget {
|
||||||
final Invoice invoice;
|
final Invoice invoice;
|
||||||
final User customer;
|
final User customer;
|
||||||
@@ -49,15 +47,13 @@ class InvoiceEditor extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _InvoiceEditorState extends State<InvoiceEditor> {
|
class _InvoiceEditorState extends State<InvoiceEditor> {
|
||||||
User _user;
|
|
||||||
|
|
||||||
var dateFormatter = new DateFormat('dd MMM yyyy');
|
var dateFormatter = new DateFormat('dd MMM yyyy');
|
||||||
|
|
||||||
Invoice _invoice;
|
Invoice _invoice;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
bool _isNew;
|
bool _isNew;
|
||||||
|
User _user;
|
||||||
|
|
||||||
List<bool> isSelected = [false];
|
|
||||||
bool _showCartons = false;
|
bool _showCartons = false;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -141,11 +137,14 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
var rateModel = Provider.of<ShipmentRateModel>(context);
|
var rateModel = Provider.of<ShipmentRateModel>(context);
|
||||||
var rate = rateModel.rate;
|
var rate = rateModel.rate;
|
||||||
|
|
||||||
|
final invoiceNumberBox = DisplayText(
|
||||||
|
labelTextKey: 'invoice.number',
|
||||||
|
iconData: FontAwesomeIcons.fileInvoice,
|
||||||
|
text: _invoice?.invoiceNumber ?? "");
|
||||||
final statusBox = DisplayText(
|
final statusBox = DisplayText(
|
||||||
text: _invoice?.status ?? "",
|
text: _invoice?.status ?? "",
|
||||||
iconData: Icons.av_timer,
|
iconData: Icons.av_timer,
|
||||||
labelTextKey: 'invoice.status');
|
labelTextKey: 'invoice.status');
|
||||||
|
|
||||||
final cartonTable = InvoiceCartonTable(
|
final cartonTable = InvoiceCartonTable(
|
||||||
cartons: _invoice.cartons,
|
cartons: _invoice.cartons,
|
||||||
rate: rate,
|
rate: rate,
|
||||||
@@ -155,21 +154,6 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
final customTableHeaderBox = LocalTitle(
|
|
||||||
textKey: "invoice.custom_fee",
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: Icon(Icons.add_circle, color: primaryColor),
|
|
||||||
onPressed: () async {
|
|
||||||
CustomDuty customDuty = await Navigator.of(context).push(
|
|
||||||
CupertinoPageRoute(
|
|
||||||
builder: (context) => CustomList(selected: true)));
|
|
||||||
_addCustom(customDuty);
|
|
||||||
}));
|
|
||||||
final customTableBox = InvoiceCustomTable(
|
|
||||||
customDuties: _invoice.customDuties,
|
|
||||||
onAdd: (c) => _addCustom(c),
|
|
||||||
onRemove: (c) => _removeCustom(c),
|
|
||||||
);
|
|
||||||
final paymentTypesBox = LocalDropdown<PaymentMethod>(
|
final paymentTypesBox = LocalDropdown<PaymentMethod>(
|
||||||
callback: (v) {
|
callback: (v) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -238,7 +222,6 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
},
|
},
|
||||||
isSelected: [_showCartons],
|
isSelected: [_showCartons],
|
||||||
);
|
);
|
||||||
|
|
||||||
final popupMenu = LocalPopupMenuButton(
|
final popupMenu = LocalPopupMenuButton(
|
||||||
buttonIcon: Icons.add_circle,
|
buttonIcon: Icons.add_circle,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
@@ -271,12 +254,12 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
Shipment shipment = await Navigator.of(context).push(
|
Shipment shipment = await Navigator.of(context).push(
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
InvoiceShipmentTable(shipments: _invoice.shipments)));
|
InvoiceHandlingFeeList(shipments: _invoice.shipments)));
|
||||||
_addShipment(shipment);
|
_addShipment(shipment);
|
||||||
} else if (p.id == 3) {
|
} else if (p.id == 3) {
|
||||||
Discount discount =
|
Discount discount =
|
||||||
await Navigator.of(context).push(CupertinoPageRoute(
|
await Navigator.of(context).push(CupertinoPageRoute(
|
||||||
builder: (context) => InvoiceDiscountTable(
|
builder: (context) => InvoiceDiscountList(
|
||||||
discounts: discounts,
|
discounts: discounts,
|
||||||
)));
|
)));
|
||||||
if (discount != null) {
|
if (discount != null) {
|
||||||
@@ -292,6 +275,39 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final headerBox = Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(dateFormatter.format(_invoice.invoiceDate)),
|
||||||
|
SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
Text(_user?.name ?? ""),
|
||||||
|
Text(
|
||||||
|
_user?.fcsID ?? "",
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
toggleButtonsBox,
|
||||||
|
popupMenu,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final createBtn = LocalButton(
|
||||||
|
textKey: "invoice.issue.btn",
|
||||||
|
callBack: _save,
|
||||||
|
);
|
||||||
|
|
||||||
return LocalProgress(
|
return LocalProgress(
|
||||||
inAsyncCall: _isLoading,
|
inAsyncCall: _isLoading,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
@@ -310,39 +326,8 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Row(
|
headerBox,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
_isNew ? Container() : invoiceNumberBox,
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(dateFormatter.format(_invoice.invoiceDate)),
|
|
||||||
SizedBox(
|
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
Text(_user?.name ?? ""),
|
|
||||||
Text(
|
|
||||||
_user?.fcsID ?? "",
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Spacer(),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
toggleButtonsBox,
|
|
||||||
popupMenu,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
_isNew
|
|
||||||
? Container()
|
|
||||||
: DisplayText(
|
|
||||||
labelTextKey: 'invoice.number',
|
|
||||||
iconData: FontAwesomeIcons.fileInvoice,
|
|
||||||
text: _invoice?.invoiceNumber ?? ""),
|
|
||||||
_isNew ? Container() : statusBox,
|
_isNew ? Container() : statusBox,
|
||||||
_showCartons ? cartonTable : Container(),
|
_showCartons ? cartonTable : Container(),
|
||||||
_showCartons
|
_showCartons
|
||||||
@@ -360,15 +345,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
height: 10,
|
height: 10,
|
||||||
),
|
),
|
||||||
_isNew
|
_isNew
|
||||||
? Container()
|
? createBtn
|
||||||
: LocalTitle(
|
|
||||||
textKey: "invoice.payment_attachment",
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: Icon(Icons.add_circle, color: primaryColor),
|
|
||||||
onPressed: () async {})),
|
|
||||||
_isNew
|
|
||||||
? fcsButton(
|
|
||||||
context, getLocalString(context, 'invoice.btn_create'))
|
|
||||||
: mainModel.isCustomer()
|
: mainModel.isCustomer()
|
||||||
? Container()
|
? Container()
|
||||||
: Container(
|
: Container(
|
||||||
@@ -421,5 +398,54 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_save() {}
|
_save() async {
|
||||||
|
var rateModel = Provider.of<ShipmentRateModel>(context, listen: false);
|
||||||
|
double amount = _invoice.getNetAmount(rateModel.rate);
|
||||||
|
if (_invoice.paymentMethod == null) {
|
||||||
|
showMsgDialog(context, "Error", "Payment method required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<CargoType> cargoTypes = _invoice.getCargoTypes(rateModel.rate);
|
||||||
|
if (cargoTypes == null || cargoTypes.length == 0) {
|
||||||
|
showMsgDialog(context, "Error", "Expected at least one cargo type");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((amount ?? 0) <= 0) {
|
||||||
|
showMsgDialog(context, "Error", "Expected positive amount");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
InvoiceModel invoiceModel =
|
||||||
|
Provider.of<InvoiceModel>(context, listen: false);
|
||||||
|
|
||||||
|
Invoice invoice = Invoice();
|
||||||
|
invoice.cargoTypes = cargoTypes;
|
||||||
|
invoice.amount = amount;
|
||||||
|
invoice.handlingFee = _invoice.getHandlingFee();
|
||||||
|
invoice.cartons = _invoice.cartons.where((c) => c.isChecked).toList();
|
||||||
|
invoice.shipments =
|
||||||
|
_invoice.shipments.where((s) => s.isSelected).toList();
|
||||||
|
invoice.discount = _invoice.discount;
|
||||||
|
invoice.deliveryFee = _invoice.deliveryFee;
|
||||||
|
|
||||||
|
invoice.userID = widget.customer.id;
|
||||||
|
invoice.fcsShipmentID = widget.fcsShipment.id;
|
||||||
|
invoice.invoiceDate = _invoice.invoiceDate;
|
||||||
|
invoice.paymentMethod = _invoice.paymentMethod;
|
||||||
|
|
||||||
|
await invoiceModel.createInvoice(invoice);
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,12 +8,12 @@ import 'package:flutter/material.dart';
|
|||||||
typedef OnAdd(Shipment shipment);
|
typedef OnAdd(Shipment shipment);
|
||||||
typedef OnRemove(Shipment shipment);
|
typedef OnRemove(Shipment shipment);
|
||||||
|
|
||||||
class InvoiceShipmentTable extends StatelessWidget {
|
class InvoiceHandlingFeeList extends StatelessWidget {
|
||||||
final List<Shipment> shipments;
|
final List<Shipment> shipments;
|
||||||
final OnAdd onAdd;
|
final OnAdd onAdd;
|
||||||
final OnRemove onRemove;
|
final OnRemove onRemove;
|
||||||
|
|
||||||
const InvoiceShipmentTable(
|
const InvoiceHandlingFeeList(
|
||||||
{Key key, this.shipments, this.onAdd, this.onRemove})
|
{Key key, this.shipments, this.onAdd, this.onRemove})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
import 'package:fcs/domain/entities/custom_duty.dart';
|
|
||||||
import 'package:fcs/helpers/theme.dart';
|
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
|
||||||
import 'package:fcs/pages/widgets/my_data_table.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
typedef OnAdd(CustomDuty customDuty);
|
|
||||||
typedef OnRemove(CustomDuty customDuty);
|
|
||||||
|
|
||||||
class InvoiceCustomTable extends StatelessWidget {
|
|
||||||
final List<CustomDuty> customDuties;
|
|
||||||
final OnAdd onAdd;
|
|
||||||
final OnRemove onRemove;
|
|
||||||
|
|
||||||
const InvoiceCustomTable(
|
|
||||||
{Key key, this.customDuties, this.onAdd, this.onRemove})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MyDataTable(
|
|
||||||
headingRowHeight: 40,
|
|
||||||
columns: [
|
|
||||||
MyDataColumn(
|
|
||||||
label: LocalText(
|
|
||||||
context,
|
|
||||||
"rate.cutom.product_type",
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
MyDataColumn(
|
|
||||||
label: LocalText(
|
|
||||||
context,
|
|
||||||
"rate.custom.fee",
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
rows: getRows(context),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MyDataRow> getRows(BuildContext context) {
|
|
||||||
if (customDuties == null) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
double total = 0;
|
|
||||||
var rows = customDuties.map((c) {
|
|
||||||
total += c.fee;
|
|
||||||
return MyDataRow(
|
|
||||||
cells: [
|
|
||||||
MyDataCell(new Text(
|
|
||||||
c.productType == null ? "" : c.productType,
|
|
||||||
style: textStyle,
|
|
||||||
)),
|
|
||||||
MyDataCell(
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
Text(c.fee == null ? "0" : c.fee.toString(), style: textStyle),
|
|
||||||
onRemove == null
|
|
||||||
? SizedBox(
|
|
||||||
width: 50,
|
|
||||||
)
|
|
||||||
: IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.remove_circle,
|
|
||||||
color: primaryColor,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
if (onRemove != null) onRemove(c);
|
|
||||||
})
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
var totalRow = MyDataRow(
|
|
||||||
onSelectChanged: (bool selected) {},
|
|
||||||
cells: [
|
|
||||||
MyDataCell(Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
"invoice.total_custom_fee",
|
|
||||||
color: Colors.black87,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
MyDataCell(
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 48.0),
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: Text(total.toString(),
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
rows.add(totalRow);
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@ import 'package:fcs/domain/entities/fcs_shipment.dart';
|
|||||||
import 'package:fcs/domain/entities/user.dart';
|
import 'package:fcs/domain/entities/user.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/customer/model/customer_model.dart';
|
import 'package:fcs/pages/customer/model/customer_model.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_editor.dart';
|
import 'package:fcs/pages/invoice/editor/invoice_editor.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
import 'package:fcs/pages/widgets/progress.dart';
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
@@ -82,12 +82,15 @@ class _InvoiceCustomerListState extends State<InvoiceCustomerList> {
|
|||||||
|
|
||||||
Widget _item(User customer) {
|
Widget _item(User customer) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
Navigator.of(context).push(CupertinoPageRoute(
|
bool created = await Navigator.of(context).push(CupertinoPageRoute(
|
||||||
builder: (context) => InvoiceEditor(
|
builder: (context) => InvoiceEditor(
|
||||||
customer: customer,
|
customer: customer,
|
||||||
fcsShipment: widget.fcsShipment,
|
fcsShipment: widget.fcsShipment,
|
||||||
)));
|
)));
|
||||||
|
if (created ?? false) {
|
||||||
|
_load();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 12.0, right: 12),
|
padding: const EdgeInsets.only(left: 12.0, right: 12),
|
||||||
|
|||||||
@@ -1,170 +1,60 @@
|
|||||||
|
import 'package:fcs/domain/constants.dart';
|
||||||
import 'package:fcs/domain/entities/carton.dart';
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
import 'package:fcs/domain/entities/cargo_type.dart';
|
|
||||||
import 'package:fcs/domain/entities/custom_duty.dart';
|
|
||||||
import 'package:fcs/domain/entities/discount.dart';
|
|
||||||
import 'package:fcs/domain/entities/invoice.dart';
|
import 'package:fcs/domain/entities/invoice.dart';
|
||||||
import 'package:fcs/domain/entities/payment_method.dart';
|
|
||||||
import 'package:fcs/domain/entities/user.dart';
|
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/localization/app_translations.dart';
|
import 'package:fcs/pages/carton/model/carton_model.dart';
|
||||||
import 'package:fcs/pages/discount/discount_list.dart';
|
import 'package:fcs/pages/invoice/editor/invoice_carton_table.dart';
|
||||||
import 'package:fcs/pages/discount/model/discount_model.dart';
|
import 'package:fcs/pages/invoice/invoice_table.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_editor.dart';
|
import 'package:fcs/pages/invoice/model/invoice_model.dart';
|
||||||
import 'package:fcs/pages/main/model/language_model.dart';
|
import 'package:fcs/pages/invoice/widgets.dart';
|
||||||
import 'package:fcs/pages/main/model/main_model.dart';
|
|
||||||
import 'package:fcs/pages/main/util.dart';
|
import 'package:fcs/pages/main/util.dart';
|
||||||
import 'package:fcs/pages/payment_methods/model/payment_method_model.dart';
|
|
||||||
import 'package:fcs/pages/rates/custom_list.dart';
|
|
||||||
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
|
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
|
||||||
import 'package:fcs/pages/user_search/user_serach.dart';
|
|
||||||
import 'package:fcs/pages/widgets/bottom_up_page_route.dart';
|
|
||||||
import 'package:fcs/pages/widgets/discount_dropdown.dart';
|
|
||||||
import 'package:fcs/pages/widgets/display_text.dart';
|
import 'package:fcs/pages/widgets/display_text.dart';
|
||||||
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
|
import 'package:fcs/pages/widgets/fcs_icons.dart';
|
||||||
import 'package:fcs/pages/widgets/input_text.dart';
|
import 'package:fcs/pages/widgets/local_button.dart';
|
||||||
import 'package:fcs/pages/widgets/local_dropdown.dart';
|
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
import 'package:fcs/pages/widgets/local_title.dart';
|
|
||||||
import 'package:fcs/pages/widgets/multi_img_controller.dart';
|
|
||||||
import 'package:fcs/pages/widgets/multi_img_file.dart';
|
|
||||||
import 'package:fcs/pages/widgets/my_data_table.dart';
|
|
||||||
import 'package:fcs/pages/widgets/progress.dart';
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_icons/flutter_icons.dart';
|
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class InvoiceInfoPage extends StatefulWidget {
|
class InvoiceInfo extends StatefulWidget {
|
||||||
final Invoice invoice;
|
final Invoice invoice;
|
||||||
final User customer;
|
InvoiceInfo({this.invoice});
|
||||||
InvoiceInfoPage({this.invoice, this.customer});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_InvoiceInfoPageState createState() => _InvoiceInfoPageState();
|
_InvoiceInfoState createState() => _InvoiceInfoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
|
class _InvoiceInfoState extends State<InvoiceInfo> {
|
||||||
User user;
|
|
||||||
|
|
||||||
var dateFormatter = new DateFormat('dd MMM yyyy');
|
var dateFormatter = new DateFormat('dd MMM yyyy');
|
||||||
TextEditingController _invoiceNumberController = new TextEditingController();
|
|
||||||
TextEditingController _dateController = new TextEditingController();
|
|
||||||
TextEditingController _nameController = new TextEditingController();
|
|
||||||
TextEditingController _phoneController = new TextEditingController();
|
|
||||||
TextEditingController _discountController = new TextEditingController();
|
|
||||||
TextEditingController _amountController = new TextEditingController();
|
|
||||||
TextEditingController _statusController = new TextEditingController();
|
|
||||||
TextEditingController _customFeeController = new TextEditingController();
|
|
||||||
MultiImgController multiImgController = MultiImgController();
|
|
||||||
TextEditingController _descriptionController = new TextEditingController();
|
|
||||||
TextEditingController _balanceController = new TextEditingController();
|
|
||||||
|
|
||||||
Invoice _invoice;
|
Invoice _invoice;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
List<Carton> _boxes = [];
|
|
||||||
bool isSwitched = false;
|
|
||||||
int deliveryfee = 0;
|
|
||||||
double customFee = 0;
|
|
||||||
double total = 0;
|
|
||||||
Discount _discount;
|
|
||||||
bool isNew = false;
|
|
||||||
Discount selectedDiscount;
|
|
||||||
int selectedDiscountAmt;
|
|
||||||
PaymentMethod paymentMethod;
|
|
||||||
double volumetricRatio = 0;
|
|
||||||
|
|
||||||
List<Carton> selectedBoxes = [];
|
|
||||||
List<CustomDuty> customs = [];
|
|
||||||
|
|
||||||
List<CargoType> _cargoTypes = [
|
|
||||||
CargoType(id: "1", name: 'General Cargo', weight: 33, rate: 6),
|
|
||||||
CargoType(id: "2", name: 'Medicine', weight: 33, rate: 7),
|
|
||||||
CargoType(id: "3", name: 'Dangerous Cargo', weight: 33, rate: 8)
|
|
||||||
];
|
|
||||||
|
|
||||||
List<String> _receipts = [
|
|
||||||
"assets/buying_online_with_first_last_name.png",
|
|
||||||
];
|
|
||||||
|
|
||||||
|
bool _showCartons = false;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
volumetricRatio = Provider.of<ShipmentRateModel>(context, listen: false)
|
_invoice = widget.invoice;
|
||||||
.rate
|
_invoice.shipments?.forEach((s) {
|
||||||
.volumetricRatio;
|
s.isSelected = true;
|
||||||
|
});
|
||||||
|
_loadCartons();
|
||||||
|
}
|
||||||
|
|
||||||
if (widget.invoice != null) {
|
_loadCartons() async {
|
||||||
_invoice = widget.invoice;
|
CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false);
|
||||||
_invoiceNumberController.text = _invoice.invoiceNumber;
|
List<Carton> cartons = [];
|
||||||
_dateController.text = dateFormatter.format(_invoice.invoiceDate);
|
for (var c in _invoice?.cartons ?? []) {
|
||||||
_nameController.text = _invoice.userName;
|
var _carton = await cartonModel.getCarton(c.id);
|
||||||
_phoneController.text = _invoice.phoneNumber;
|
_carton.isChecked = true;
|
||||||
// _amountController.text = _invoice.getAmount.toString();
|
cartons.add(_carton);
|
||||||
_amountController.text = _invoice.amount.toString();
|
|
||||||
_statusController.text = _invoice.status.toString();
|
|
||||||
_customFeeController.text = '0';
|
|
||||||
// multiImgController.setImageUrls = _receipts;
|
|
||||||
_descriptionController.text = 'For Electronics goods';
|
|
||||||
// _boxes = _invoice.packages;
|
|
||||||
} else {
|
|
||||||
_dateController.text = dateFormatter.format(DateTime.now());
|
|
||||||
_amountController.text = '0';
|
|
||||||
_customFeeController.text = '0';
|
|
||||||
_descriptionController.text = '';
|
|
||||||
_balanceController.text = '0';
|
|
||||||
setState(() {
|
|
||||||
isNew = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
setState(() {
|
||||||
_boxes = [
|
_invoice.cartons = cartons;
|
||||||
Carton(
|
});
|
||||||
shipmentNumber: "A202",
|
|
||||||
receiverNumber: "3",
|
|
||||||
receiverName: "Ko Myo Min",
|
|
||||||
boxNumber: "1",
|
|
||||||
rate: 7,
|
|
||||||
packageType: "General",
|
|
||||||
weight: 75,
|
|
||||||
status: "Packed",
|
|
||||||
receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon',
|
|
||||||
cargoDesc: "Clothes",
|
|
||||||
arrivedDate: DateTime(2020, 6, 1),
|
|
||||||
width: 10,
|
|
||||||
height: 10,
|
|
||||||
length: 10,
|
|
||||||
// packages: packages,
|
|
||||||
// statusHistory: statusHistory,
|
|
||||||
cargoTypes: [
|
|
||||||
CargoType(name: 'General Cargo', weight: 25),
|
|
||||||
CargoType(name: 'Medicine', weight: 20),
|
|
||||||
CargoType(name: 'Dangerous Cargo', weight: 30)
|
|
||||||
]),
|
|
||||||
Carton(
|
|
||||||
shipmentNumber: "A202",
|
|
||||||
receiverNumber: "3",
|
|
||||||
receiverName: "Ko Myo Min",
|
|
||||||
boxNumber: "2",
|
|
||||||
rate: 7,
|
|
||||||
packageType: "General",
|
|
||||||
weight: 75,
|
|
||||||
status: "Packed",
|
|
||||||
cargoDesc: "Clothes",
|
|
||||||
arrivedDate: DateTime(2020, 6, 1),
|
|
||||||
width: 10,
|
|
||||||
height: 10,
|
|
||||||
length: 10,
|
|
||||||
// statusHistory: statusHistory,
|
|
||||||
// packages: packages,
|
|
||||||
receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon',
|
|
||||||
cargoTypes: [
|
|
||||||
CargoType(name: 'General Cargo', weight: 25),
|
|
||||||
CargoType(name: 'Medicine', weight: 20),
|
|
||||||
CargoType(name: 'Dangerous Cargo', weight: 30)
|
|
||||||
])
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -174,21 +64,91 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final nameBox = DisplayText(
|
bool isCanceled = _invoice.status == invoice_cancel_status;
|
||||||
iconData: Feather.user,
|
var rateModel = Provider.of<ShipmentRateModel>(context);
|
||||||
labelTextKey: 'invoice.customer_name',
|
var rate = rateModel.rate;
|
||||||
text: user != null ? user.name : 'Ko Nyi');
|
|
||||||
|
|
||||||
final fcsIDBox = DisplayText(
|
final cartonTable = InvoiceCartonTable(
|
||||||
text: user != null ? user.fcsID : "FCS-KRUTUG",
|
cartons: _invoice.cartons,
|
||||||
labelTextKey: "box.fcs.id",
|
rate: rate,
|
||||||
icon: FcsIDIcon(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final statusBox = DisplayText(
|
final invoiceTableBox = InvoiceTable(
|
||||||
text: _statusController.text,
|
invoice: _invoice,
|
||||||
iconData: Icons.av_timer,
|
rate: rate,
|
||||||
labelTextKey: 'invoice.status');
|
deliveryFeeSelected: (selected) {
|
||||||
|
setState(() {
|
||||||
|
if (selected) {
|
||||||
|
_invoice.deliveryFee = rate.deliveryFee;
|
||||||
|
} else {
|
||||||
|
_invoice.deliveryFee = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
discountSelected: (discount) {
|
||||||
|
setState(() {
|
||||||
|
_invoice.discount = discount;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
final toggleButtonsBox = ToggleButtons(
|
||||||
|
color: Colors.black45,
|
||||||
|
selectedColor: Colors.black45,
|
||||||
|
disabledColor: Colors.grey,
|
||||||
|
selectedBorderColor: primaryColor,
|
||||||
|
borderColor: Colors.transparent,
|
||||||
|
fillColor: Colors.transparent,
|
||||||
|
highlightColor: Colors.black45,
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(cartonIconData),
|
||||||
|
],
|
||||||
|
onPressed: (int index) {
|
||||||
|
setState(() {
|
||||||
|
_showCartons = !_showCartons;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isSelected: [_showCartons],
|
||||||
|
);
|
||||||
|
|
||||||
|
final headerBox = Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(dateFormatter.format(_invoice.invoiceDate)),
|
||||||
|
SizedBox(
|
||||||
|
height: 5,
|
||||||
|
),
|
||||||
|
Text(_invoice?.userName ?? ""),
|
||||||
|
Text(
|
||||||
|
_invoice?.fcsID ?? "",
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
toggleButtonsBox,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final paymentMethodBox = DisplayText(
|
||||||
|
labelTextKey: "invoice.payment_method",
|
||||||
|
text: _invoice.paymentMethod.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
final receiptsBtn = LocalButton(
|
||||||
|
textKey: "invoice.btn_payment_receipt",
|
||||||
|
callBack: _cancel,
|
||||||
|
);
|
||||||
|
final cancelBtn = LocalButton(
|
||||||
|
textKey: "invoice.cancel.btn",
|
||||||
|
callBack: _cancel,
|
||||||
|
);
|
||||||
|
|
||||||
return LocalProgress(
|
return LocalProgress(
|
||||||
inAsyncCall: _isLoading,
|
inAsyncCall: _isLoading,
|
||||||
@@ -203,71 +163,30 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
|
|||||||
shadowColor: Colors.transparent,
|
shadowColor: Colors.transparent,
|
||||||
title: LocalText(context, 'invoice.form.title',
|
title: LocalText(context, 'invoice.form.title',
|
||||||
color: primaryColor, fontSize: 20),
|
color: primaryColor, fontSize: 20),
|
||||||
actions: [
|
|
||||||
new IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.delete,
|
|
||||||
color: primaryColor,
|
|
||||||
),
|
|
||||||
onPressed: () {}),
|
|
||||||
new IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.edit,
|
|
||||||
color: primaryColor,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).push(CupertinoPageRoute(
|
|
||||||
builder: (context) => InvoiceEditor(invoice: _invoice)));
|
|
||||||
})
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
LocalTitle(textKey: "invoice.customer_info"),
|
getInvoiceStatus(context, _invoice),
|
||||||
DisplayText(
|
headerBox,
|
||||||
labelTextKey: 'invoice.date',
|
_showCartons ? cartonTable : Container(),
|
||||||
iconData: Icons.date_range,
|
_showCartons
|
||||||
text: _dateController.text),
|
? Divider(
|
||||||
widget.invoice == null
|
color: primaryColor,
|
||||||
? Container()
|
thickness: 2,
|
||||||
: DisplayText(
|
)
|
||||||
labelTextKey: 'invoice.number',
|
|
||||||
iconData: FontAwesomeIcons.fileInvoice,
|
|
||||||
text: _invoiceNumberController.text),
|
|
||||||
fcsIDBox,
|
|
||||||
nameBox,
|
|
||||||
statusBox,
|
|
||||||
LocalTitle(textKey: "invoice.box_info"),
|
|
||||||
Center(child: Column(children: getCartonRows(context))),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
LocalTitle(textKey: "invoice.custom_fee"),
|
|
||||||
Column(children: getCustomFeeRows(context)),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
LocalTitle(textKey: "invoice.cargo_type"),
|
|
||||||
Column(children: getCargoTableByBox(context)),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.only(top: 5, left: 18),
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: LocalText(context, 'invoice.payment_method',
|
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.grey,
|
|
||||||
fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'${paymentMethod != null ? paymentMethod.accountName : "KBZ Bank"}',
|
|
||||||
style: TextStyle(fontSize: 16)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 30),
|
|
||||||
!isNew
|
|
||||||
? LocalTitle(textKey: "invoice.payment_attachment")
|
|
||||||
: Container(),
|
: Container(),
|
||||||
|
invoiceTableBox,
|
||||||
|
SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
paymentMethodBox,
|
||||||
|
SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
isCanceled ? Container() : receiptsBtn,
|
||||||
|
isCanceled ? Container() : cancelBtn,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -275,528 +194,27 @@ class _InvoiceInfoPageState extends State<InvoiceInfoPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCartonRows(BuildContext context) {
|
_cancel() {
|
||||||
List<Widget> dataRow = [];
|
showConfirmDialog(context, "invoice.cancel.confirm", _cancelInvoice);
|
||||||
|
|
||||||
dataRow = _boxes.map((box) {
|
|
||||||
return Container(
|
|
||||||
height: 50,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(box.packageNumber),
|
|
||||||
Text(box.shipmentNumber),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Text(
|
|
||||||
box.length == null
|
|
||||||
? ""
|
|
||||||
: box.length.toString() +
|
|
||||||
' x ' +
|
|
||||||
box.length.toString() +
|
|
||||||
' x ' +
|
|
||||||
box.height.toString(),
|
|
||||||
textAlign: TextAlign.center)),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
box.getShipmentWeight(volumetricRatio).toString()))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
0,
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 5.0, bottom: 15.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
"invoice.box.number",
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: Text('L x W x H',
|
|
||||||
style: TextStyle(color: Colors.grey)))),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
"invoice.shipment_weight",
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
return dataRow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getCustomFeeRows(BuildContext context) {
|
_cancelInvoice() async {
|
||||||
customFee = 0;
|
setState(() {
|
||||||
List<Widget> dataRow = [];
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
dataRow = customs.map((custom) {
|
try {
|
||||||
customFee += custom.fee;
|
InvoiceModel invoiceModel =
|
||||||
return Container(
|
Provider.of<InvoiceModel>(context, listen: false);
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(flex: 2, child: Text('${custom.productType}')),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Text('\$ ${custom.fee}', textAlign: TextAlign.center)),
|
|
||||||
Expanded(child: SizedBox(height: 40))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
dataRow.insert(
|
await invoiceModel.cancelInvoice(_invoice);
|
||||||
0,
|
Navigator.pop(context, true);
|
||||||
Container(
|
} catch (e) {
|
||||||
decoration: BoxDecoration(
|
showMsgDialog(context, "Error", e.toString());
|
||||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
} finally {
|
||||||
padding: const EdgeInsets.only(
|
setState(() {
|
||||||
left: 5.0, right: 5.0, top: 15.0, bottom: 15.0),
|
_isLoading = false;
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Text('Product', style: TextStyle(color: Colors.grey))),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Text('Fee',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(color: Colors.grey))),
|
|
||||||
Expanded(flex: 1, child: Container())
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 15.0, bottom: 15.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.total_custom_fee',
|
|
||||||
color: Colors.black,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Center(
|
|
||||||
child: Text('\$ $customFee',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold)))),
|
|
||||||
Expanded(
|
|
||||||
child: Container(),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
return dataRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
getCargoTableByBox(BuildContext context) {
|
|
||||||
total = 0;
|
|
||||||
List<Widget> dataRow = _cargoTypes.map((cargo) {
|
|
||||||
var amount = cargo.weight * cargo.rate;
|
|
||||||
total += amount;
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 15.0, bottom: 15.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(flex: 2, child: Text('${cargo.rate}')),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Text('${cargo.weight} x ${cargo.rate}',
|
|
||||||
textAlign: TextAlign.center)),
|
|
||||||
Expanded(
|
|
||||||
child: Text('\$ $amount',
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
)))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
dataRow.insert(
|
|
||||||
0,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 15.0, bottom: 15.0),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(bottom: BorderSide(color: Colors.grey))),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Text(getLocalString(context, 'invoice.box.cargo_type'),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.grey))),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Text(
|
|
||||||
getLocalString(context, 'cargo.weight') +
|
|
||||||
' x ' +
|
|
||||||
getLocalString(context, 'cargo.rate'),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.grey))),
|
|
||||||
Expanded(
|
|
||||||
child: Text(getLocalString(context, 'invoice.amount'),
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.grey)))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 10.0, bottom: 10.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.total',
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
'\$ $total',
|
|
||||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(left: 5.0, right: 5.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.discount_value',
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
'\$ ${_discount != null ? _discount.amount.toInt() : 0}',
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
)))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 10.0, bottom: 0.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.custom_fee',
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Expanded(
|
|
||||||
child: Text('\$ $customFee',
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 20.0, bottom: 5.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.handling_fee',
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Expanded(
|
|
||||||
child: Text('\$ 10.0',
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 10.0, bottom: 10.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.delivery_fee',
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text('\$ $deliveryfee',
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
)))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text('')),
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Divider(
|
|
||||||
thickness: 3,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
)));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 10.0, bottom: 10.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.net_amount',
|
|
||||||
color: Colors.black,
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text('\$ ${getTotalBalance(total)}',
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: primaryColor)))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
dataRow.insert(
|
|
||||||
dataRow.length,
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 5.0, right: 5.0, top: 10.0, bottom: 10.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: LocalText(
|
|
||||||
context,
|
|
||||||
'invoice.balance',
|
|
||||||
color: Colors.black,
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text('\$ ${getTotalBalance(total)}',
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: primaryColor)))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
return dataRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
getTotalBalance(total) {
|
|
||||||
double balance = 0;
|
|
||||||
double custom = customFee != 0 ? customFee.toDouble() : 0;
|
|
||||||
double deliveryFee = deliveryfee != 0 ? deliveryfee.toDouble() : 0;
|
|
||||||
double discount = _discount != null ? _discount.amount.toDouble() : 0;
|
|
||||||
balance = (total + custom + deliveryFee) - discount;
|
|
||||||
return balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MyDataRow> getBoxRow(BuildContext context) {
|
|
||||||
return _boxes.map((p) {
|
|
||||||
p.cargoTypes.map((cargo) {
|
|
||||||
_cargoTypes.asMap().map((index, _cargo) {
|
|
||||||
if (_cargo.id == cargo.id) {
|
|
||||||
setState(() {
|
|
||||||
_cargoTypes[index].weight += cargo.weight;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return MyDataRow(
|
}
|
||||||
onSelectChanged: (bool selected) {},
|
|
||||||
cells: [
|
|
||||||
MyDataCell(Checkbox(
|
|
||||||
value: true,
|
|
||||||
onChanged: (value) {
|
|
||||||
selectedBoxes.add(p);
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
MyDataCell(new Text(
|
|
||||||
p.boxNumber == null
|
|
||||||
? ""
|
|
||||||
: '${p.shipmentNumber}-${p.receiverNumber} #${p.boxNumber}',
|
|
||||||
style: textStyle,
|
|
||||||
)),
|
|
||||||
MyDataCell(new Text(
|
|
||||||
p.length == null
|
|
||||||
? ""
|
|
||||||
: p.length.toString() +
|
|
||||||
' x ' +
|
|
||||||
p.length.toString() +
|
|
||||||
' x ' +
|
|
||||||
p.height.toString(),
|
|
||||||
style: textStyle,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MyDataRow> getCargoDataRow(BuildContext context) {
|
|
||||||
return _cargoTypes.asMap().entries.map((c) {
|
|
||||||
var cargo = c.value;
|
|
||||||
var amt = cargo.weight * cargo.rate;
|
|
||||||
return MyDataRow(
|
|
||||||
onSelectChanged: (bool selected) {},
|
|
||||||
cells: [
|
|
||||||
MyDataCell(new Text(
|
|
||||||
cargo.name,
|
|
||||||
style: textStyle,
|
|
||||||
)),
|
|
||||||
MyDataCell(new Text(
|
|
||||||
cargo.weight.toString() + ' x ' + cargo.rate.toString(),
|
|
||||||
style: textStyle,
|
|
||||||
)),
|
|
||||||
MyDataCell(new Text(
|
|
||||||
"\$$amt",
|
|
||||||
style: textStyle,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}).toList()
|
|
||||||
// .insert(_cargoTypes.length,MyDataRow(cells: [
|
|
||||||
// MyDataCell(new Text('')),
|
|
||||||
// MyDataCell(new Text('Total')),
|
|
||||||
// MyDataCell(new Text(
|
|
||||||
// "\$5000",
|
|
||||||
// style: textStyle,
|
|
||||||
// )),
|
|
||||||
// ])
|
|
||||||
// )
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:fcs/helpers/api_helper.dart';
|
||||||
|
import 'package:fcs/helpers/firebase_helper.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_shipment_list.dart';
|
import 'package:fcs/pages/invoice/invoice_shipment_list.dart';
|
||||||
import 'package:fcs/pages/invoice/model/invoice_model.dart';
|
import 'package:fcs/pages/invoice/model/invoice_model.dart';
|
||||||
|
import 'package:fcs/pages/invoice/payment_pdf_screen.dart';
|
||||||
import 'package:fcs/pages/widgets/local_popup_menu_button.dart';
|
import 'package:fcs/pages/widgets/local_popup_menu_button.dart';
|
||||||
import 'package:fcs/pages/widgets/local_popupmenu.dart';
|
import 'package:fcs/pages/widgets/local_popupmenu.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
@@ -21,7 +26,6 @@ class InvoiceList extends StatefulWidget {
|
|||||||
|
|
||||||
class _InvoiceListState extends State<InvoiceList> {
|
class _InvoiceListState extends State<InvoiceList> {
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
bool _showPaid = false;
|
|
||||||
var _controller = ScrollController();
|
var _controller = ScrollController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -34,7 +38,8 @@ class _InvoiceListState extends State<InvoiceList> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Provider.of<InvoiceModel>(context, listen: false).initData(false);
|
Provider.of<InvoiceModel>(context, listen: false)
|
||||||
|
.initData(widget.forCustomer, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -51,15 +56,29 @@ class _InvoiceListState extends State<InvoiceList> {
|
|||||||
popmenus: [
|
popmenus: [
|
||||||
LocalPopupMenu(
|
LocalPopupMenu(
|
||||||
id: 1,
|
id: 1,
|
||||||
textKey: "invoice.popupmenu.pending",
|
textKey: "invoice.popupmenu.issused",
|
||||||
selected: invoiceModel.selectedIndex == 1),
|
selected: invoiceModel.selectedIndex == 1),
|
||||||
LocalPopupMenu(
|
LocalPopupMenu(
|
||||||
id: 2,
|
id: 2,
|
||||||
textKey: "invoice.popupmenu.paid",
|
textKey: "invoice.popupmenu.paid",
|
||||||
selected: invoiceModel.selectedIndex == 2)
|
selected: invoiceModel.selectedIndex == 2),
|
||||||
|
LocalPopupMenu(
|
||||||
|
id: 3,
|
||||||
|
textKey: "invoice.popupmenu.cancel",
|
||||||
|
selected: invoiceModel.selectedIndex == 3)
|
||||||
],
|
],
|
||||||
popupMenuCallback: (p) => this.setState(() {
|
popupMenuCallback: (p) => this.setState(() {
|
||||||
_showPaid = p.id == 2;
|
invoiceModel.selectedIndex = p.id;
|
||||||
|
if (p.id == 2) {
|
||||||
|
Provider.of<InvoiceModel>(context, listen: false)
|
||||||
|
.initData(widget.forCustomer, false, true);
|
||||||
|
} else if (p.id == 3) {
|
||||||
|
Provider.of<InvoiceModel>(context, listen: false)
|
||||||
|
.initData(widget.forCustomer, true, false);
|
||||||
|
} else {
|
||||||
|
Provider.of<InvoiceModel>(context, listen: false)
|
||||||
|
.initData(widget.forCustomer, true, false);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -131,7 +150,7 @@ class _InvoiceListState extends State<InvoiceList> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_newInvoice() {
|
_newInvoice() async {
|
||||||
Navigator.of(context)
|
Navigator.of(context)
|
||||||
.push(CupertinoPageRoute(builder: (context) => InvoiceShipmentList()));
|
.push(CupertinoPageRoute(builder: (context) => InvoiceShipmentList()));
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:fcs/domain/constants.dart';
|
||||||
import 'package:fcs/domain/entities/invoice.dart';
|
import 'package:fcs/domain/entities/invoice.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/invoice/invoice_info.dart';
|
import 'package:fcs/pages/invoice/invoice_info.dart';
|
||||||
import 'package:fcs/pages/widgets/bottom_up_page_route.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -12,7 +12,6 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
import 'invoice_editor.dart';
|
|
||||||
import 'payment_page.dart';
|
import 'payment_page.dart';
|
||||||
import 'payment_pdf_screen.dart';
|
import 'payment_pdf_screen.dart';
|
||||||
|
|
||||||
@@ -81,11 +80,11 @@ class _InvoiceListRowState extends State<InvoiceListRow> {
|
|||||||
owner
|
owner
|
||||||
? Navigator.of(context).push(CupertinoPageRoute(
|
? Navigator.of(context).push(CupertinoPageRoute(
|
||||||
builder: (context) => PaymentPDFScreen(
|
builder: (context) => PaymentPDFScreen(
|
||||||
path: pdfPath,
|
url: _invoice.invoiceURL,
|
||||||
)))
|
)))
|
||||||
: Navigator.of(context).push(CupertinoPageRoute(
|
: Navigator.of(context).push(CupertinoPageRoute(
|
||||||
builder: (context) => PaymentPDFScreen(
|
builder: (context) => PaymentPDFScreen(
|
||||||
path: pdfPath,
|
url: _invoice.invoiceURL,
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
child: new Row(
|
child: new Row(
|
||||||
@@ -132,7 +131,7 @@ class _InvoiceListRowState extends State<InvoiceListRow> {
|
|||||||
// padding: const EdgeInsets.all(0),
|
// padding: const EdgeInsets.all(0),
|
||||||
// child: getStatus(_invoice.status),
|
// child: getStatus(_invoice.status),
|
||||||
// ),
|
// ),
|
||||||
_invoice.status == "Pending"
|
_invoice.status == invoice_issued_status
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsets.only(left: 10.0),
|
padding: const EdgeInsets.only(left: 10.0),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
@@ -191,10 +190,11 @@ class _InvoiceListRowState extends State<InvoiceListRow> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
//to go invoice info page
|
//to go invoice info page
|
||||||
|
Navigator.pop(context);
|
||||||
Navigator.of(context).push(CupertinoPageRoute(
|
Navigator.of(context).push(CupertinoPageRoute(
|
||||||
builder: (context) => InvoiceInfoPage(invoice: _invoice)));
|
builder: (context) => InvoiceInfo(invoice: _invoice)));
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import 'package:fcs/domain/entities/fcs_shipment.dart';
|
import 'package:fcs/domain/entities/fcs_shipment.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart';
|
import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart';
|
||||||
import 'package:fcs/pages/shipment/model/shipment_model.dart';
|
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
import 'package:fcs/pages/widgets/progress.dart';
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'invoice_customer_list.dart';
|
||||||
import 'invoice_shipment_list_row.dart';
|
import 'invoice_shipment_list_row.dart';
|
||||||
|
|
||||||
class InvoiceShipmentList extends StatefulWidget {
|
class InvoiceShipmentList extends StatefulWidget {
|
||||||
@@ -65,7 +65,14 @@ class _InvoiceShipmentListState extends State<InvoiceShipmentList> {
|
|||||||
itemCount: _fcsShipments.length,
|
itemCount: _fcsShipments.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return InvoiceShipmentListRow(
|
return InvoiceShipmentListRow(
|
||||||
fcsShipment: _fcsShipments[index]);
|
fcsShipment: _fcsShipments[index],
|
||||||
|
onSelect: (f) {
|
||||||
|
Navigator.of(context).push(CupertinoPageRoute(
|
||||||
|
builder: (context) => InvoiceCustomerList(
|
||||||
|
fcsShipment: f,
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -8,9 +8,12 @@ import 'package:intl/intl.dart';
|
|||||||
import '../main/util.dart';
|
import '../main/util.dart';
|
||||||
import 'invoice_customer_list.dart';
|
import 'invoice_customer_list.dart';
|
||||||
|
|
||||||
|
typedef OnSelect(FcsShipment fcsShipment);
|
||||||
|
|
||||||
class InvoiceShipmentListRow extends StatefulWidget {
|
class InvoiceShipmentListRow extends StatefulWidget {
|
||||||
|
final OnSelect onSelect;
|
||||||
final FcsShipment fcsShipment;
|
final FcsShipment fcsShipment;
|
||||||
const InvoiceShipmentListRow({this.fcsShipment});
|
const InvoiceShipmentListRow({this.fcsShipment, this.onSelect});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_InvoiceShipmentListRowState createState() => _InvoiceShipmentListRowState();
|
_InvoiceShipmentListRowState createState() => _InvoiceShipmentListRowState();
|
||||||
@@ -35,10 +38,7 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
|
|||||||
padding: EdgeInsets.only(left: 15, right: 15),
|
padding: EdgeInsets.only(left: 15, right: 15),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(CupertinoPageRoute(
|
if (widget.onSelect != null) widget.onSelect(widget.fcsShipment);
|
||||||
builder: (context) => InvoiceCustomerList(
|
|
||||||
fcsShipment: _fcsShipment,
|
|
||||||
)));
|
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
|||||||
@@ -63,14 +63,14 @@ class InvoiceTable extends StatelessWidget {
|
|||||||
List<InvoiceTableRow> getTableRows() {
|
List<InvoiceTableRow> getTableRows() {
|
||||||
List<InvoiceTableRow> tableRows = [];
|
List<InvoiceTableRow> tableRows = [];
|
||||||
// add cargo types
|
// add cargo types
|
||||||
List<CargoType> _cargoTypes = invoice.getCargoTypes(rate);
|
List<CargoType> _cargoTypes = invoice.getCargoTypes(rate) ?? [];
|
||||||
_cargoTypes.forEach((c) {
|
_cargoTypes.forEach((c) {
|
||||||
tableRows.add(InvoiceTableRow(
|
tableRows.add(InvoiceTableRow(
|
||||||
invoiceDataType: InvoiceDataType.CargoDataType,
|
invoiceDataType: InvoiceDataType.CargoDataType,
|
||||||
desc: c.name,
|
desc: c.name,
|
||||||
rate:
|
rate:
|
||||||
"${c.calWeight.toStringAsFixed(2)} x ${c.calRate.toStringAsFixed(2)}",
|
"${c.calWeight.toStringAsFixed(2)} x ${c.calRate.toStringAsFixed(2)}",
|
||||||
amount: "${c.amount.toStringAsFixed(2)}"));
|
amount: "${c.calAmount.toStringAsFixed(2)}"));
|
||||||
});
|
});
|
||||||
invoice.shipments.where((ss) => (ss.isSelected ?? false)).forEach((s) {
|
invoice.shipments.where((ss) => (ss.isSelected ?? false)).forEach((s) {
|
||||||
tableRows.add(InvoiceTableRow(
|
tableRows.add(InvoiceTableRow(
|
||||||
@@ -80,7 +80,7 @@ class InvoiceTable extends StatelessWidget {
|
|||||||
rate: "",
|
rate: "",
|
||||||
amount: "${s.handlingFee.toStringAsFixed(2)}"));
|
amount: "${s.handlingFee.toStringAsFixed(2)}"));
|
||||||
});
|
});
|
||||||
// add custom fee
|
// // add custom fee
|
||||||
invoice.customDuties.forEach((c) {
|
invoice.customDuties.forEach((c) {
|
||||||
tableRows.add(InvoiceTableRow(
|
tableRows.add(InvoiceTableRow(
|
||||||
data: c,
|
data: c,
|
||||||
@@ -89,7 +89,7 @@ class InvoiceTable extends StatelessWidget {
|
|||||||
rate: "",
|
rate: "",
|
||||||
amount: "${c.fee.toStringAsFixed(2)}"));
|
amount: "${c.fee.toStringAsFixed(2)}"));
|
||||||
});
|
});
|
||||||
// add delivery fee
|
// // add delivery fee
|
||||||
tableRows.add(InvoiceTableRow(
|
tableRows.add(InvoiceTableRow(
|
||||||
data: invoice.deliveryFee == null || invoice.deliveryFee == 0
|
data: invoice.deliveryFee == null || invoice.deliveryFee == 0
|
||||||
? null
|
? null
|
||||||
@@ -99,7 +99,7 @@ class InvoiceTable extends StatelessWidget {
|
|||||||
rate: "",
|
rate: "",
|
||||||
amount: "${invoice?.deliveryFee?.toStringAsFixed(2) ?? '0'}"));
|
amount: "${invoice?.deliveryFee?.toStringAsFixed(2) ?? '0'}"));
|
||||||
|
|
||||||
// add discounts
|
// // add discounts
|
||||||
if (invoice.discount != null) {
|
if (invoice.discount != null) {
|
||||||
tableRows.add(InvoiceTableRow(
|
tableRows.add(InvoiceTableRow(
|
||||||
data: invoice.discount,
|
data: invoice.discount,
|
||||||
|
|||||||
@@ -1,33 +1,30 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:fcs/config.dart';
|
||||||
|
import 'package:fcs/data/services/services.dart';
|
||||||
import 'package:fcs/domain/constants.dart';
|
import 'package:fcs/domain/constants.dart';
|
||||||
import 'package:fcs/domain/entities/invoice.dart';
|
import 'package:fcs/domain/entities/invoice.dart';
|
||||||
import 'package:fcs/domain/entities/receipt.dart';
|
import 'package:fcs/helpers/api_helper.dart';
|
||||||
|
import 'package:fcs/helpers/firebase_helper.dart';
|
||||||
import 'package:fcs/helpers/paginator.dart';
|
import 'package:fcs/helpers/paginator.dart';
|
||||||
import 'package:fcs/pages/main/model/base_model.dart';
|
import 'package:fcs/pages/main/model/base_model.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
class InvoiceModel extends BaseModel {
|
class InvoiceModel extends BaseModel {
|
||||||
final log = Logger('InvoiceModel');
|
final log = Logger('InvoiceModel');
|
||||||
|
|
||||||
StreamSubscription<QuerySnapshot> listener;
|
StreamSubscription<QuerySnapshot> listener;
|
||||||
|
|
||||||
List<Invoice> _invoices = [
|
List<Invoice> _invoices = [];
|
||||||
Invoice(
|
|
||||||
invoiceNumber: 'A092(A)-33',
|
|
||||||
invoiceDate: DateTime(2020, 4, 6, 12, 15),
|
|
||||||
userName: 'Ko Myo Min',
|
|
||||||
phoneNumber: '+959 555555555',
|
|
||||||
amount: 300,
|
|
||||||
status: 'Pending',
|
|
||||||
)
|
|
||||||
];
|
|
||||||
|
|
||||||
List<Invoice> get invoices =>
|
List<Invoice> get invoices =>
|
||||||
_selectedIndex == 1 ? _invoices : List<Invoice>.from(_paid.values);
|
_selectedIndex == 1 ? _invoices : List<Invoice>.from(_paginator.values);
|
||||||
|
|
||||||
Paginator _paid;
|
Paginator _paginator;
|
||||||
|
|
||||||
bool endOfPaidInvoices = false;
|
bool endOfPaidInvoices = false;
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
@@ -45,15 +42,17 @@ class InvoiceModel extends BaseModel {
|
|||||||
super.privilegeChanged();
|
super.privilegeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
initData(bool forCustomer) {
|
initData(bool forCustomer, bool isCanceled, bool isPaid) {
|
||||||
_selectedIndex = 1;
|
_loadInvoices(forCustomer);
|
||||||
// _loadFcsInvoices(forCustomer);
|
|
||||||
|
|
||||||
if (_paid != null) _paid.close();
|
if (_paginator != null) _paginator.close();
|
||||||
_paid = _getPaid(forCustomer);
|
_paginator = _getPaginator(forCustomer, isCanceled, isPaid);
|
||||||
|
_paginator.load(onFinished: () {
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadFcsInvoices(bool forCustomer) async {
|
Future<void> _loadInvoices(bool forCustomer) async {
|
||||||
if (user == null) return;
|
if (user == null) return;
|
||||||
if (!forCustomer && !user.hasInvoices()) return;
|
if (!forCustomer && !user.hasInvoices()) return;
|
||||||
String path = "/$invoices_collection";
|
String path = "/$invoices_collection";
|
||||||
@@ -63,7 +62,7 @@ class InvoiceModel extends BaseModel {
|
|||||||
try {
|
try {
|
||||||
var q = Firestore.instance
|
var q = Firestore.instance
|
||||||
.collection("$path")
|
.collection("$path")
|
||||||
.where("is_paid", isEqualTo: false)
|
.where("status", isEqualTo: invoice_issued_status)
|
||||||
.where("is_deleted", isEqualTo: false);
|
.where("is_deleted", isEqualTo: false);
|
||||||
|
|
||||||
if (forCustomer) {
|
if (forCustomer) {
|
||||||
@@ -84,18 +83,24 @@ class InvoiceModel extends BaseModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Paginator _getPaid(bool isCustomer) {
|
Paginator _getPaginator(bool isCustomer, bool isCanceled, bool isPaid) {
|
||||||
if (!isCustomer) {
|
if (!isCustomer) {
|
||||||
if (user == null || !(user.hasInvoices())) throw "No privilege";
|
if (user == null || !(user.hasInvoices())) throw "No privilege";
|
||||||
}
|
}
|
||||||
var pageQuery = Firestore.instance
|
var pageQuery = Firestore.instance
|
||||||
.collection("/$packages_collection")
|
.collection("/$invoices_collection")
|
||||||
.where("is_delivered", isEqualTo: true)
|
|
||||||
.where("is_deleted", isEqualTo: false);
|
.where("is_deleted", isEqualTo: false);
|
||||||
if (isCustomer) {
|
if (isCustomer) {
|
||||||
pageQuery = pageQuery.where("user_id", isEqualTo: user.id);
|
pageQuery = pageQuery.where("user_id", isEqualTo: user.id);
|
||||||
}
|
}
|
||||||
pageQuery = pageQuery.orderBy("status_date", descending: true);
|
if (isCanceled) {
|
||||||
|
pageQuery = pageQuery.where("status", isEqualTo: invoice_cancel_status);
|
||||||
|
}
|
||||||
|
if (isPaid) {
|
||||||
|
pageQuery = pageQuery.where("status", isEqualTo: invoice_paid_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
pageQuery = pageQuery.orderBy("created_at", descending: true);
|
||||||
var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) {
|
var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) {
|
||||||
return Invoice.fromMap(data, id);
|
return Invoice.fromMap(data, id);
|
||||||
});
|
});
|
||||||
@@ -103,11 +108,11 @@ class InvoiceModel extends BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadMore({bool isCustomer}) async {
|
Future<void> loadMore({bool isCustomer}) async {
|
||||||
if (_paid.ended || _selectedIndex == 1)
|
if (_paginator.ended || _selectedIndex == 1)
|
||||||
return; // when paid menu is not selected return
|
return; // when paid menu is not selected return
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
await _paid.load(onFinished: () {
|
await _paginator.load(onFinished: () {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
});
|
});
|
||||||
@@ -115,7 +120,7 @@ class InvoiceModel extends BaseModel {
|
|||||||
|
|
||||||
Future<void> refresh({bool isCustomer}) async {
|
Future<void> refresh({bool isCustomer}) async {
|
||||||
if (_selectedIndex == 1) return; // when paid menu is not selected return
|
if (_selectedIndex == 1) return; // when paid menu is not selected return
|
||||||
await _paid.refresh(onFinished: () {
|
await _paginator.refresh(onFinished: () {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -125,16 +130,24 @@ class InvoiceModel extends BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logout() async {
|
logout() async {
|
||||||
if (_paid != null) _paid.close();
|
if (_paginator != null) _paginator.close();
|
||||||
if (listener != null) await listener.cancel();
|
if (listener != null) await listener.cancel();
|
||||||
_invoices = [];
|
_invoices = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createInvoice(Invoice invoice) {
|
Future<void> createInvoice(Invoice invoice) async {
|
||||||
// return Services.instance.invoiceService.createInvoice(invoice);
|
File file = await downloadPDF("invoice", invoice.toMap());
|
||||||
|
String url = await uploadStorage("pdfs", file);
|
||||||
|
print("uploaded url: $url");
|
||||||
|
invoice.invoiceURL = url;
|
||||||
|
return Services.instance.invoiceService.createInvoice(invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateInvoice(Invoice invoice) {
|
Future<void> updateInvoice(Invoice invoice) {
|
||||||
// return Services.instance.invoiceService.updateInvoice(invoice);
|
return Services.instance.invoiceService.updateInvoice(invoice);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> cancelInvoice(Invoice invoice) {
|
||||||
|
return Services.instance.invoiceService.cancelInvoice(invoice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:fcs/helpers/cache_mgr.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/main/model/main_model.dart';
|
import 'package:fcs/pages/main/util.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_pdfview/flutter_pdfview.dart';
|
import 'package:flutter_pdfview/flutter_pdfview.dart';
|
||||||
import 'package:http/http.dart' as http;
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:share/share.dart';
|
import 'package:share/share.dart';
|
||||||
|
|
||||||
class PaymentPDFScreen extends StatefulWidget {
|
class PaymentPDFScreen extends StatefulWidget {
|
||||||
final String path;
|
final String url;
|
||||||
|
|
||||||
PaymentPDFScreen({Key key, this.path}) : super(key: key);
|
PaymentPDFScreen({Key key, this.url}) : super(key: key);
|
||||||
|
|
||||||
_PaymentPDFScreenState createState() => _PaymentPDFScreenState();
|
_PaymentPDFScreenState createState() => _PaymentPDFScreenState();
|
||||||
}
|
}
|
||||||
@@ -30,88 +27,100 @@ class _PaymentPDFScreenState extends State<PaymentPDFScreen>
|
|||||||
int currentPage = 0;
|
int currentPage = 0;
|
||||||
bool isReady = false;
|
bool isReady = false;
|
||||||
String errorMessage = '';
|
String errorMessage = '';
|
||||||
|
bool _isLoading = true;
|
||||||
|
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
download();
|
||||||
|
}
|
||||||
|
|
||||||
|
File file;
|
||||||
|
Future<void> download() async {
|
||||||
|
try {
|
||||||
|
File f = await PdfCacheMgr.pdfs.getSingleFile(widget.url);
|
||||||
|
setState(() {
|
||||||
|
file = f;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return LocalProgress(
|
||||||
appBar: AppBar(
|
inAsyncCall: _isLoading,
|
||||||
centerTitle: true,
|
child: Scaffold(
|
||||||
backgroundColor: primaryColor,
|
appBar: AppBar(
|
||||||
title: LocalText(context, 'invoice.pdf',
|
centerTitle: true,
|
||||||
color: Colors.white, fontSize: 20),
|
backgroundColor: Colors.white,
|
||||||
leading: new IconButton(
|
shadowColor: Colors.transparent,
|
||||||
icon: new Icon(CupertinoIcons.back),
|
title: LocalText(context, 'invoice.pdf',
|
||||||
onPressed: () {
|
color: Colors.white, fontSize: 20),
|
||||||
Navigator.of(context).pop();
|
leading: new IconButton(
|
||||||
}),
|
icon: new Icon(CupertinoIcons.back, color: primaryColor),
|
||||||
actions: <Widget>[
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.file_download),
|
|
||||||
onPressed: () async {
|
|
||||||
var file = await copyAsset();
|
|
||||||
print('file=> $file');
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
IconButton(
|
actions: <Widget>[
|
||||||
icon: Icon(Icons.share),
|
IconButton(
|
||||||
onPressed: () => _share(widget.path),
|
icon: Icon(
|
||||||
),
|
Icons.share,
|
||||||
],
|
color: primaryColor,
|
||||||
),
|
),
|
||||||
body: Stack(
|
onPressed: _share,
|
||||||
children: <Widget>[
|
),
|
||||||
PDFView(
|
],
|
||||||
filePath: widget.path,
|
),
|
||||||
enableSwipe: true,
|
body: Stack(
|
||||||
swipeHorizontal: true,
|
children: <Widget>[
|
||||||
autoSpacing: false,
|
_isLoading
|
||||||
pageFling: true,
|
? Container()
|
||||||
pageSnap: true,
|
: PDFView(
|
||||||
defaultPage: currentPage,
|
filePath: file?.path ?? "",
|
||||||
fitPolicy: FitPolicy.BOTH,
|
enableSwipe: true,
|
||||||
preventLinkNavigation:
|
swipeHorizontal: true,
|
||||||
false, // if set to true the link is handled in flutter
|
autoSpacing: false,
|
||||||
onRender: (_pages) {
|
pageFling: true,
|
||||||
print(('pages => $pages'));
|
pageSnap: true,
|
||||||
setState(() {
|
defaultPage: currentPage,
|
||||||
pages = _pages;
|
fitPolicy: FitPolicy.BOTH,
|
||||||
isReady = true;
|
preventLinkNavigation:
|
||||||
});
|
false, // if set to true the link is handled in flutter
|
||||||
},
|
onRender: (_pages) {
|
||||||
onViewCreated: (PDFViewController pdfViewController) {
|
print(('pages => $pages'));
|
||||||
_controller.complete(pdfViewController);
|
setState(() {
|
||||||
},
|
pages = _pages;
|
||||||
onLinkHandler: (String uri) {
|
isReady = true;
|
||||||
print('goto uri: $uri');
|
});
|
||||||
},
|
},
|
||||||
onPageChanged: (int page, int total) {
|
onViewCreated: (PDFViewController pdfViewController) {
|
||||||
print('page change: $page/$total');
|
_controller.complete(pdfViewController);
|
||||||
setState(() {
|
},
|
||||||
currentPage = page;
|
onLinkHandler: (String uri) {
|
||||||
});
|
print('goto uri: $uri');
|
||||||
},
|
},
|
||||||
),
|
onPageChanged: (int page, int total) {
|
||||||
],
|
print('page change: $page/$total');
|
||||||
|
setState(() {
|
||||||
|
currentPage = page;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_share(String url) async {
|
_share() async {
|
||||||
MainModel mainModel = Provider.of<MainModel>(context, listen: false);
|
|
||||||
String appUrl = mainModel.setting.appUrl;
|
|
||||||
final RenderBox box = context.findRenderObject();
|
final RenderBox box = context.findRenderObject();
|
||||||
await Share.share(
|
await Share.shareFiles([file.path],
|
||||||
"Join us on FCS Logistics App. Here is the link:\n $appUrl\n" + url,
|
mimeTypes: ["application/pdf"],
|
||||||
subject: "Invitation to FCS Logistics App",
|
subject: "Invoice",
|
||||||
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
|
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File> copyAsset() async {
|
|
||||||
Directory tempDir = await getTemporaryDirectory();
|
|
||||||
String tempPath = tempDir.path;
|
|
||||||
File tempFile = File('$tempPath/Invoice-A092(A)-32.pdf');
|
|
||||||
ByteData bd = await rootBundle.load('assets/Invoice-A092(A)-32.pdf');
|
|
||||||
await tempFile.writeAsBytes(bd.buffer.asUint8List(), flush: true);
|
|
||||||
return tempFile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
24
lib/pages/invoice/widgets.dart
Normal file
24
lib/pages/invoice/widgets.dart
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import 'package:fcs/domain/entities/invoice.dart';
|
||||||
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
Widget getInvoiceStatus(BuildContext context, Invoice invoice) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
LocalText(
|
||||||
|
context,
|
||||||
|
'',
|
||||||
|
text: invoice.invoiceNumber ?? "",
|
||||||
|
color: primaryColor,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
|
child: Chip(label: Text(invoice.status ?? "")),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ import 'package:fcs/pages/delivery/delivery_list.dart';
|
|||||||
import 'package:fcs/pages/discount/discount_list.dart';
|
import 'package:fcs/pages/discount/discount_list.dart';
|
||||||
import 'package:fcs/pages/faq/faq_list_page.dart';
|
import 'package:fcs/pages/faq/faq_list_page.dart';
|
||||||
import 'package:fcs/pages/fcs_shipment/fcs_shipment_list.dart';
|
import 'package:fcs/pages/fcs_shipment/fcs_shipment_list.dart';
|
||||||
import 'package:fcs/pages/invoice/invoce_list.dart';
|
import 'package:fcs/pages/invoice/invoice_list.dart';
|
||||||
import 'package:fcs/pages/main/model/language_model.dart';
|
import 'package:fcs/pages/main/model/language_model.dart';
|
||||||
import 'package:fcs/pages/main/model/main_model.dart';
|
import 'package:fcs/pages/main/model/main_model.dart';
|
||||||
import 'package:fcs/pages/main/util.dart';
|
import 'package:fcs/pages/main/util.dart';
|
||||||
@@ -298,11 +298,11 @@ class _HomePageState extends State<HomePage> {
|
|||||||
final invoicesBtn = TaskButton("invoices.btn",
|
final invoicesBtn = TaskButton("invoices.btn",
|
||||||
icon: FontAwesomeIcons.fileInvoice,
|
icon: FontAwesomeIcons.fileInvoice,
|
||||||
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
|
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
|
||||||
builder: (context) => InvoiceList(forCustomer: false))));
|
builder: (context) => InvoiceList(forCustomer: true))));
|
||||||
final invoicesBtnFcs = TaskButton("invoices.btn",
|
final invoicesBtnFcs = TaskButton("invoices.btn",
|
||||||
icon: FontAwesomeIcons.fileInvoice,
|
icon: FontAwesomeIcons.fileInvoice,
|
||||||
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
|
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
|
||||||
builder: (context) => InvoiceList(forCustomer: true))));
|
builder: (context) => InvoiceList(forCustomer: false))));
|
||||||
|
|
||||||
final discountBtn = TaskButton("discount.btn",
|
final discountBtn = TaskButton("discount.btn",
|
||||||
icon: Entypo.price_ribbon,
|
icon: Entypo.price_ribbon,
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ class _ShipmentListState extends State<ShipmentList> {
|
|||||||
if (p.id == 3) {
|
if (p.id == 3) {
|
||||||
Provider.of<ShipmentModel>(context, listen: false)
|
Provider.of<ShipmentModel>(context, listen: false)
|
||||||
.initData(widget.forCustomer, myPickup: true);
|
.initData(widget.forCustomer, myPickup: true);
|
||||||
} else if (p.id == 1) {
|
} else {
|
||||||
Provider.of<ShipmentModel>(context, listen: false)
|
Provider.of<ShipmentModel>(context, listen: false)
|
||||||
.initData(widget.forCustomer);
|
.initData(widget.forCustomer, myPickup: false);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
43
pubspec.lock
43
pubspec.lock
@@ -28,7 +28,7 @@ packages:
|
|||||||
name: cached_network_image
|
name: cached_network_image
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2+1"
|
version: "2.3.3"
|
||||||
camera:
|
camera:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -176,6 +176,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -246,13 +253,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.6"
|
version: "3.1.6"
|
||||||
fixnum:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: fixnum
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.10.11"
|
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -266,12 +266,12 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.5.0"
|
||||||
flutter_cache_manager:
|
flutter_cache_manager:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_cache_manager
|
name: flutter_cache_manager
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.2"
|
version: "2.0.0"
|
||||||
flutter_datetime_picker:
|
flutter_datetime_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -454,7 +454,7 @@ packages:
|
|||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.14"
|
version: "1.6.22"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -476,6 +476,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "1.0.3"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.4+1"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -546,13 +553,6 @@ packages:
|
|||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
protobuf:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: protobuf
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.1"
|
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -768,6 +768,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.8"
|
version: "2.0.8"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.7.3"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ dependencies:
|
|||||||
flutter_local_notifications: ^1.4.4+4
|
flutter_local_notifications: ^1.4.4+4
|
||||||
share: ^0.6.5
|
share: ^0.6.5
|
||||||
cached_network_image: ^2.3.2+1
|
cached_network_image: ^2.3.2+1
|
||||||
|
flutter_cache_manager: ^2.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user