@soostori/desktop-adapter 0.1.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/auth-pin.d.ts +16 -0
  2. package/dist/auth-pin.d.ts.map +1 -0
  3. package/dist/auth-pin.js +14 -0
  4. package/dist/auth-pin.js.map +1 -0
  5. package/dist/business-repository.d.ts +31 -0
  6. package/dist/business-repository.d.ts.map +1 -0
  7. package/dist/business-repository.js +61 -0
  8. package/dist/business-repository.js.map +1 -0
  9. package/dist/categories-repository.d.ts +15 -0
  10. package/dist/categories-repository.d.ts.map +1 -0
  11. package/dist/categories-repository.js +35 -0
  12. package/dist/categories-repository.js.map +1 -0
  13. package/dist/customers-repository.d.ts +20 -0
  14. package/dist/customers-repository.d.ts.map +1 -0
  15. package/dist/customers-repository.js +95 -0
  16. package/dist/customers-repository.js.map +1 -0
  17. package/dist/debts-repository.d.ts +48 -0
  18. package/dist/debts-repository.d.ts.map +1 -0
  19. package/dist/debts-repository.js +57 -0
  20. package/dist/debts-repository.js.map +1 -0
  21. package/dist/devices-repository.d.ts +29 -0
  22. package/dist/devices-repository.d.ts.map +1 -0
  23. package/dist/devices-repository.js +120 -0
  24. package/dist/devices-repository.js.map +1 -0
  25. package/dist/domain-repositories.d.ts +12 -0
  26. package/dist/domain-repositories.d.ts.map +1 -0
  27. package/dist/domain-repositories.js +12 -0
  28. package/dist/domain-repositories.js.map +1 -0
  29. package/dist/index.d.ts +25 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +25 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/inventory-repository.d.ts +31 -0
  34. package/dist/inventory-repository.d.ts.map +1 -0
  35. package/dist/inventory-repository.js +127 -0
  36. package/dist/inventory-repository.js.map +1 -0
  37. package/dist/products-repository-mappers.d.ts +77 -0
  38. package/dist/products-repository-mappers.d.ts.map +1 -0
  39. package/dist/products-repository-mappers.js +75 -0
  40. package/dist/products-repository-mappers.js.map +1 -0
  41. package/dist/products-repository-read.d.ts +17 -0
  42. package/dist/products-repository-read.d.ts.map +1 -0
  43. package/dist/products-repository-read.js +51 -0
  44. package/dist/products-repository-read.js.map +1 -0
  45. package/dist/products-repository-stock.d.ts +28 -0
  46. package/dist/products-repository-stock.d.ts.map +1 -0
  47. package/dist/products-repository-stock.js +57 -0
  48. package/dist/products-repository-stock.js.map +1 -0
  49. package/dist/products-repository-types.d.ts +51 -0
  50. package/dist/products-repository-types.d.ts.map +1 -0
  51. package/dist/products-repository-types.js +5 -0
  52. package/dist/products-repository-types.js.map +1 -0
  53. package/dist/products-repository-variants.d.ts +19 -0
  54. package/dist/products-repository-variants.d.ts.map +1 -0
  55. package/dist/products-repository-variants.js +26 -0
  56. package/dist/products-repository-variants.js.map +1 -0
  57. package/dist/products-repository-write.d.ts +14 -0
  58. package/dist/products-repository-write.d.ts.map +1 -0
  59. package/dist/products-repository-write.js +99 -0
  60. package/dist/products-repository-write.js.map +1 -0
  61. package/dist/products-repository.d.ts +69 -0
  62. package/dist/products-repository.d.ts.map +1 -0
  63. package/dist/products-repository.js +48 -0
  64. package/dist/products-repository.js.map +1 -0
  65. package/dist/sales-repository.d.ts +95 -0
  66. package/dist/sales-repository.d.ts.map +1 -0
  67. package/dist/sales-repository.js +160 -0
  68. package/dist/sales-repository.js.map +1 -0
  69. package/dist/sqlite-database.d.ts +16 -0
  70. package/dist/sqlite-database.d.ts.map +1 -0
  71. package/dist/sqlite-database.js +24 -0
  72. package/dist/sqlite-database.js.map +1 -0
  73. package/dist/sqlite-repository.d.ts +18 -0
  74. package/dist/sqlite-repository.d.ts.map +1 -0
  75. package/dist/sqlite-repository.js +61 -0
  76. package/dist/sqlite-repository.js.map +1 -0
  77. package/dist/sqlite-transaction.d.ts +13 -0
  78. package/dist/sqlite-transaction.d.ts.map +1 -0
  79. package/dist/sqlite-transaction.js +35 -0
  80. package/dist/sqlite-transaction.js.map +1 -0
  81. package/package.json +40 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * ProductsRepository type definitions — shared interfaces for the repository module.
3
+ */
4
+ import type { ProductId, CategoryId, ProductVariantId, ISO8601, Money } from '@soostori/core';
5
+ export type { ProductId, CategoryId, ProductVariantId, ISO8601, Money };
6
+ /** Full product insert input — includes Desktop-extended fields not in SDK Product. */
7
+ export interface ProductCreateInput {
8
+ name: string;
9
+ categoryId?: string | null;
10
+ sku?: string | null;
11
+ barcode?: string | null;
12
+ description?: string | null;
13
+ imageUrl?: string | null;
14
+ costPrice?: Money;
15
+ sellingPrice: Money;
16
+ discountPrice?: Money | null;
17
+ unit?: string;
18
+ stockQuantity?: number;
19
+ lowStockThreshold?: number;
20
+ trackInventory?: boolean;
21
+ hasVariants?: boolean;
22
+ allowSingleUnitSale?: boolean;
23
+ distributorName?: string | null;
24
+ distributorPhone?: string | null;
25
+ isActive?: boolean;
26
+ [key: string]: unknown;
27
+ }
28
+ /** Full category insert input. */
29
+ export interface CategoryCreateInput {
30
+ name: string;
31
+ description?: string | null;
32
+ icon?: string | null;
33
+ color?: string;
34
+ displayOrder?: number;
35
+ isActive?: boolean;
36
+ }
37
+ /** Local ProductVariant — mirrors @soostori/business/products ProductVariant */
38
+ export interface ProductVariant {
39
+ id: ProductVariantId;
40
+ productId: ProductId;
41
+ name: string;
42
+ sku: string | null;
43
+ barcode: string | null;
44
+ costPrice: Money | null;
45
+ sellingPrice: Money | null;
46
+ stockQuantity: number;
47
+ metadata: Record<string, unknown> | null;
48
+ createdAt: ISO8601;
49
+ updatedAt: ISO8601;
50
+ }
51
+ //# sourceMappingURL=products-repository-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository-types.d.ts","sourceRoot":"","sources":["../src/products-repository-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC7F,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AAEvE,uFAAuF;AACvF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,YAAY,EAAE,KAAK,CAAA;IACnB,aAAa,CAAC,EAAE,KAAK,GAAG,IAAI,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,kCAAkC;AAClC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,gBAAgB,CAAA;IACpB,SAAS,EAAE,SAAS,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAA;IACvB,YAAY,EAAE,KAAK,GAAG,IAAI,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACxC,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;CACnB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * ProductsRepository type definitions — shared interfaces for the repository module.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=products-repository-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository-types.js","sourceRoot":"","sources":["../src/products-repository-types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Product variant operations.
3
+ */
4
+ import type { ProductVariant } from './products-repository-types.js';
5
+ import type { ProductId } from './products-repository-types.js';
6
+ export declare class ProductsVariantRepository {
7
+ findVariants(productId: ProductId): Promise<ProductVariant[]>;
8
+ createVariant(data: {
9
+ productId: import('@soostori/core').UUID;
10
+ name: string;
11
+ sku?: string | null;
12
+ barcode?: string | null;
13
+ costPrice?: import('@soostori/core').Money | null;
14
+ sellingPrice?: import('@soostori/core').Money | null;
15
+ stockQuantity?: number;
16
+ metadata?: Record<string, unknown> | null;
17
+ }): Promise<ProductVariant>;
18
+ }
19
+ //# sourceMappingURL=products-repository-variants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository-variants.d.ts","sourceRoot":"","sources":["../src/products-repository-variants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAoB,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAIjF,qBAAa,yBAAyB;IAC9B,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAO7D,aAAa,CAAC,IAAI,EAAE;QACxB,SAAS,EAAE,OAAO,gBAAgB,EAAE,IAAI,CAAA;QACxC,IAAI,EAAE,MAAM,CAAA;QACZ,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,gBAAgB,EAAE,KAAK,GAAG,IAAI,CAAA;QACjD,YAAY,CAAC,EAAE,OAAO,gBAAgB,EAAE,KAAK,GAAG,IAAI,CAAA;QACpD,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;KAC1C,GAAG,OAAO,CAAC,cAAc,CAAC;CAkB5B"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Product variant operations.
3
+ */
4
+ import { getDatabase } from './sqlite-database.js';
5
+ import { randomUUID } from 'crypto';
6
+ import { rowToVariant } from './products-repository-mappers.js';
7
+ export class ProductsVariantRepository {
8
+ async findVariants(productId) {
9
+ const rows = getDatabase()
10
+ .prepare('SELECT * FROM product_variants WHERE product_id = ?')
11
+ .all(productId);
12
+ return rows.map(rowToVariant);
13
+ }
14
+ async createVariant(data) {
15
+ const db = getDatabase();
16
+ const id = randomUUID();
17
+ const now = new Date().toISOString();
18
+ db.prepare(`
19
+ INSERT INTO product_variants (id, product_id, name, sku, barcode, cost_price, selling_price, stock_quantity, metadata, created_at, updated_at)
20
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
21
+ `).run(id, data.productId, data.name, data.sku || null, data.barcode || null, data.costPrice ?? null, data.sellingPrice ?? null, data.stockQuantity ?? 0, data.metadata ? JSON.stringify(data.metadata) : null, now, now);
22
+ const row = db.prepare('SELECT * FROM product_variants WHERE id = ?').get(id);
23
+ return rowToVariant(row);
24
+ }
25
+ }
26
+ //# sourceMappingURL=products-repository-variants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository-variants.js","sourceRoot":"","sources":["../src/products-repository-variants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAInC,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAE/D,MAAM,OAAO,yBAAyB;IACpC,KAAK,CAAC,YAAY,CAAC,SAAoB;QACrC,MAAM,IAAI,GAAG,WAAW,EAAE;aACvB,OAAO,CAAC,qDAAqD,CAAC;aAC9D,GAAG,CAAC,SAAmB,CAAiB,CAAA;QAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IAC/B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IASnB;QACC,MAAM,EAAE,GAAG,WAAW,EAAE,CAAA;QACxB,MAAM,EAAE,GAAG,UAAU,EAAiC,CAAA;QACtD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QACpC,EAAE,CAAC,OAAO,CAAC;;;KAGV,CAAC,CAAC,GAAG,CACJ,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAC7B,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,EACtC,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI,EACjD,IAAI,CAAC,aAAa,IAAI,CAAC,EACvB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EACpD,GAAG,EAAE,GAAG,CACT,CAAA;QACD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC,GAAG,CAAC,EAAY,CAAe,CAAA;QACrG,OAAO,YAAY,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Products write operations — creates, updates, deletes.
3
+ */
4
+ import type { Product, Category } from '@soostori/core';
5
+ import type { ProductCreateInput, CategoryCreateInput } from './products-repository-types.js';
6
+ import type { ProductId, CategoryId } from './products-repository-types.js';
7
+ export declare class ProductsWriteRepository {
8
+ create(data: ProductCreateInput): Promise<Product>;
9
+ update(id: ProductId, changes: Partial<ProductCreateInput>): Promise<Product>;
10
+ softDelete(id: ProductId): Promise<void>;
11
+ createCategory(data: CategoryCreateInput): Promise<Category>;
12
+ updateCategory(id: CategoryId, changes: Partial<CategoryCreateInput>): Promise<Category>;
13
+ }
14
+ //# sourceMappingURL=products-repository-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository-write.d.ts","sourceRoot":"","sources":["../src/products-repository-write.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAC7F,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAgB3E,qBAAa,uBAAuB;IAC5B,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IA6BlD,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAqB7E,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxC,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAa5D,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;CAiB/F"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Products write operations — creates, updates, deletes.
3
+ */
4
+ import { getDatabase } from './sqlite-database.js';
5
+ import { randomUUID } from 'crypto';
6
+ import { rowToProduct, rowToCategory } from './products-repository-mappers.js';
7
+ const fieldMap = [
8
+ ['name', 'name'], ['categoryId', 'category_id'], ['sku', 'sku'],
9
+ ['barcode', 'barcode'], ['description', 'description'],
10
+ ['imageUrl', 'image_url'], ['costPrice', 'cost_price'],
11
+ ['sellingPrice', 'selling_price'], ['discountPrice', 'discount_price'],
12
+ ['unit', 'unit'], ['stockQuantity', 'stock_quantity'],
13
+ ['lowStockThreshold', 'low_stock_threshold'],
14
+ ['trackInventory', 'track_inventory'], ['allowSingleUnitSale', 'allow_single_unit_sale'],
15
+ ['distributorName', 'distributor_name'],
16
+ ['distributorPhone', 'distributor_phone'],
17
+ ];
18
+ export class ProductsWriteRepository {
19
+ async create(data) {
20
+ const db = getDatabase();
21
+ const id = randomUUID();
22
+ const now = new Date().toISOString();
23
+ db.prepare(`
24
+ INSERT INTO products (id, category_id, name, sku, barcode, description, image_url,
25
+ cost_price, selling_price, discount_price, unit, stock_quantity,
26
+ low_stock_threshold, track_inventory, has_variants, expiry_date,
27
+ is_active, distributor_name, distributor_phone,
28
+ barcode_generated, allow_single_unit_sale, units_per_package,
29
+ box_buying_price, bulk_selling_price, group_prices,
30
+ created_at, updated_at)
31
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
32
+ `).run(id, data.categoryId || null, data.name, data.sku || null, data.barcode || null, data.description || null, data.imageUrl || null, data.costPrice ?? 0, data.sellingPrice, data.discountPrice ?? null, data.unit || 'piece', data.stockQuantity ?? 0, data.lowStockThreshold ?? 5, data.trackInventory ? 1 : 0, 0, null, data.isActive !== undefined ? (data.isActive ? 1 : 0) : 1, data.distributorName || null, data.distributorPhone || null, 0, data.allowSingleUnitSale !== false ? 1 : 0, null, null, null, null, now, now);
33
+ const row = db.prepare('SELECT * FROM products WHERE id = ?').get(id);
34
+ return rowToProduct(row);
35
+ }
36
+ async update(id, changes) {
37
+ const db = getDatabase();
38
+ const now = new Date().toISOString();
39
+ const sets = [];
40
+ const vals = [];
41
+ for (const [sdkKey, dbCol] of fieldMap) {
42
+ const v = changes[sdkKey];
43
+ if (v !== undefined) {
44
+ sets.push(`${dbCol} = ?`);
45
+ if (sdkKey === 'trackInventory' || sdkKey === 'allowSingleUnitSale') {
46
+ vals.push(v ? 1 : 0);
47
+ }
48
+ else {
49
+ vals.push(v);
50
+ }
51
+ }
52
+ }
53
+ sets.push('updated_at = ?');
54
+ vals.push(now, id);
55
+ db.prepare(`UPDATE products SET ${sets.join(', ')} WHERE id = ?`).run(...vals);
56
+ const row = db.prepare('SELECT * FROM products WHERE id = ?').get(id);
57
+ return rowToProduct(row);
58
+ }
59
+ async softDelete(id) {
60
+ const db = getDatabase();
61
+ const now = new Date().toISOString();
62
+ db.prepare('UPDATE products SET deleted_at = ?, is_active = 0 WHERE id = ?')
63
+ .run(now, id);
64
+ }
65
+ async createCategory(data) {
66
+ const db = getDatabase();
67
+ const id = randomUUID();
68
+ const now = new Date().toISOString();
69
+ db.prepare(`
70
+ INSERT INTO categories (id, name, description, icon, color, display_order, is_active, created_at, updated_at)
71
+ VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)
72
+ `).run(id, data.name, data.description || null, data.icon || null, data.color || '#6366f1', data.displayOrder ?? 0, now, now);
73
+ const row = db.prepare('SELECT * FROM categories WHERE id = ?').get(id);
74
+ return rowToCategory(row);
75
+ }
76
+ async updateCategory(id, changes) {
77
+ const db = getDatabase();
78
+ const now = new Date().toISOString();
79
+ const catFieldMap = [
80
+ ['name', 'name'], ['description', 'description'],
81
+ ['icon', 'icon'], ['color', 'color'], ['displayOrder', 'display_order'],
82
+ ];
83
+ const sets = [];
84
+ const vals = [];
85
+ for (const [sdkKey, dbCol] of catFieldMap) {
86
+ const v = changes[sdkKey];
87
+ if (v !== undefined) {
88
+ sets.push(`${dbCol} = ?`);
89
+ vals.push(v);
90
+ }
91
+ }
92
+ sets.push('updated_at = ?');
93
+ vals.push(now, id);
94
+ db.prepare(`UPDATE categories SET ${sets.join(', ')} WHERE id = ?`).run(...vals);
95
+ const row = db.prepare('SELECT * FROM categories WHERE id = ?').get(id);
96
+ return rowToCategory(row);
97
+ }
98
+ }
99
+ //# sourceMappingURL=products-repository-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository-write.js","sourceRoot":"","sources":["../src/products-repository-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Products repository — implements @soostori/products ProductRepository over Desktop products table.
3
+ *
4
+ * Broken into focused modules:
5
+ * products-repository-read — queries (findById, findMany, findByBarcode, categories)
6
+ * products-repository-write — mutations (create, update, softDelete, categories)
7
+ * products-repository-stock — stock adjustments (increment, decrement, set)
8
+ * products-repository-variants — variant CRUD
9
+ * products-repository-mappers — row→domain type converters
10
+ * products-repository-types — shared interfaces
11
+ */
12
+ export type { ProductCreateInput, CategoryCreateInput, ProductVariant } from './products-repository-types.js';
13
+ export type { ProductId, CategoryId, ProductVariantId, ISO8601, Money } from './products-repository-types.js';
14
+ import { setCurrentMeta } from './products-repository-mappers.js';
15
+ import type { Product, Category } from '@soostori/core';
16
+ import type { ProductId, CategoryId } from './products-repository-types.js';
17
+ import type { ProductVariant } from './products-repository-types.js';
18
+ import type { UUID } from '@soostori/core';
19
+ export { setCurrentMeta };
20
+ export declare class ProductsRepository {
21
+ private read;
22
+ private write;
23
+ private stock;
24
+ private variants;
25
+ findById: (id: ProductId) => Promise<Product | null>;
26
+ findMany: (filter?: {
27
+ categoryId?: CategoryId;
28
+ search?: string;
29
+ activeOnly?: boolean;
30
+ }) => Promise<Product[]>;
31
+ findByBarcode: (barcode: string) => Promise<Product | null>;
32
+ findCategoryById: (id: CategoryId) => Promise<Category | null>;
33
+ findCategories: () => Promise<Category[]>;
34
+ create: (data: import("./products-repository-types.js").ProductCreateInput) => Promise<Product>;
35
+ update: (id: ProductId, changes: Partial<import("./products-repository-types.js").ProductCreateInput>) => Promise<Product>;
36
+ softDelete: (id: ProductId) => Promise<void>;
37
+ createCategory: (data: import("./products-repository-types.js").CategoryCreateInput) => Promise<Category>;
38
+ updateCategory: (id: CategoryId, changes: Partial<import("./products-repository-types.js").CategoryCreateInput>) => Promise<Category>;
39
+ /** Overridden to inject inventory ledger meta — called by SalesService.commit(). */
40
+ decrementStock(productId: ProductId, quantity: number): Promise<void>;
41
+ incrementStock: (productId: ProductId, quantity: number, meta?: {
42
+ reason?: string;
43
+ referenceId?: string;
44
+ userId?: string;
45
+ deviceId?: string;
46
+ shopId?: string;
47
+ }) => Promise<void>;
48
+ setStock: (productId: ProductId, newQuantity: number) => Promise<void>;
49
+ findVariants: (productId: ProductId) => Promise<ProductVariant[]>;
50
+ createVariant: (data: {
51
+ productId: import("@soostori/core").UUID;
52
+ name: string;
53
+ sku?: string | null;
54
+ barcode?: string | null;
55
+ costPrice?: import("@soostori/core").Money | null;
56
+ sellingPrice?: import("@soostori/core").Money | null;
57
+ stockQuantity?: number;
58
+ metadata?: Record<string, unknown> | null;
59
+ }) => Promise<ProductVariant>;
60
+ /** Set sale context before calling commit(). Used by the orchestrator. */
61
+ static setSaleMeta(meta: {
62
+ saleId?: string;
63
+ userId?: string;
64
+ deviceId?: string;
65
+ shopId?: string;
66
+ }): void;
67
+ private static _currentSaleMeta;
68
+ }
69
+ //# sourceMappingURL=products-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository.d.ts","sourceRoot":"","sources":["../src/products-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAC7G,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAM7G,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE1C,OAAO,EAAE,cAAc,EAAE,CAAA;AAEzB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,QAAQ,CAAkC;IAElD,QAAQ,6CAAqC;IAC7C,QAAQ;kBAnBa,CAAC;cAAuB,CAAC;kBAChD,CAAC;6BAkB8C;IAC7C,aAAa,+CAA0C;IACvD,gBAAgB,+CAA6C;IAC7D,cAAc,4BAA2C;IAEzD,MAAM,0FAAqC;IAC3C,MAAM,qHAAqC;IAC3C,UAAU,mCAAyC;IACnD,cAAc,4FAA6C;IAC3D,cAAc,wHAA6C;IAE3D,oFAAoF;IAC9E,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E,cAAc;cAAO,CAAC;mBAAqB,CAAC;cAC5C,CAAD;gBAAkB,CAAC;cAAgB,CAAC;wBADwB;IAC3D,QAAQ,+DAAuC;IAE/C,YAAY,sDAAiD;IAC7D,aAAa;;;WAvCE,CAAC;eAA2B,CAAC;iBAC1C,CAAC;oBAAwD,CAAC;qBAChB,CAAC;gBAAqB,CAAC;kCAqCJ;IAE/D,0EAA0E;IAC1E,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKxG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAK;CACrC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Products repository — implements @soostori/products ProductRepository over Desktop products table.
3
+ *
4
+ * Broken into focused modules:
5
+ * products-repository-read — queries (findById, findMany, findByBarcode, categories)
6
+ * products-repository-write — mutations (create, update, softDelete, categories)
7
+ * products-repository-stock — stock adjustments (increment, decrement, set)
8
+ * products-repository-variants — variant CRUD
9
+ * products-repository-mappers — row→domain type converters
10
+ * products-repository-types — shared interfaces
11
+ */
12
+ import { ProductsReadRepository } from './products-repository-read.js';
13
+ import { ProductsWriteRepository } from './products-repository-write.js';
14
+ import { ProductsStockRepository } from './products-repository-stock.js';
15
+ import { ProductsVariantRepository } from './products-repository-variants.js';
16
+ import { setCurrentMeta } from './products-repository-mappers.js';
17
+ export { setCurrentMeta };
18
+ export class ProductsRepository {
19
+ read = new ProductsReadRepository();
20
+ write = new ProductsWriteRepository();
21
+ stock = new ProductsStockRepository();
22
+ variants = new ProductsVariantRepository();
23
+ findById = this.read.findById.bind(this.read);
24
+ findMany = this.read.findMany.bind(this.read);
25
+ findByBarcode = this.read.findByBarcode.bind(this.read);
26
+ findCategoryById = this.read.findCategoryById.bind(this.read);
27
+ findCategories = this.read.findCategories.bind(this.read);
28
+ create = this.write.create.bind(this.write);
29
+ update = this.write.update.bind(this.write);
30
+ softDelete = this.write.softDelete.bind(this.write);
31
+ createCategory = this.write.createCategory.bind(this.write);
32
+ updateCategory = this.write.updateCategory.bind(this.write);
33
+ /** Overridden to inject inventory ledger meta — called by SalesService.commit(). */
34
+ async decrementStock(productId, quantity) {
35
+ return this.stock.decrementStock(productId, quantity, ProductsRepository._currentSaleMeta);
36
+ }
37
+ incrementStock = this.stock.incrementStock.bind(this.stock);
38
+ setStock = this.stock.setStock.bind(this.stock);
39
+ findVariants = this.variants.findVariants.bind(this.variants);
40
+ createVariant = this.variants.createVariant.bind(this.variants);
41
+ /** Set sale context before calling commit(). Used by the orchestrator. */
42
+ static setSaleMeta(meta) {
43
+ ProductsRepository._currentSaleMeta = meta;
44
+ setCurrentMeta(meta);
45
+ }
46
+ static _currentSaleMeta = {};
47
+ }
48
+ //# sourceMappingURL=products-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products-repository.js","sourceRoot":"","sources":["../src/products-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAA;AAMjE,OAAO,EAAE,cAAc,EAAE,CAAA;AAEzB,MAAM,OAAO,kBAAkB;IACrB,IAAI,GAAG,IAAI,sBAAsB,EAAE,CAAA;IACnC,KAAK,GAAG,IAAI,uBAAuB,EAAE,CAAA;IACrC,KAAK,GAAG,IAAI,uBAAuB,EAAE,CAAA;IACrC,QAAQ,GAAG,IAAI,yBAAyB,EAAE,CAAA;IAElD,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC7C,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC7C,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvD,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC7D,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEzD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3C,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnD,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3D,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAE3D,oFAAoF;IACpF,KAAK,CAAC,cAAc,CAAC,SAAoB,EAAE,QAAgB;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,CAAA;IAC5F,CAAC;IAED,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3D,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAE/C,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC7D,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAE/D,0EAA0E;IAC1E,MAAM,CAAC,WAAW,CAAC,IAA8E;QAC/F,kBAAkB,CAAC,gBAAgB,GAAG,IAAI,CAAA;QAC1C,cAAc,CAAC,IAAI,CAAC,CAAA;IACtB,CAAC;IAEO,MAAM,CAAC,gBAAgB,GAAG,EAAE,CAAA"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Sales repository — implements SalesRepository contract over Desktop sales table.
3
+ *
4
+ * Desktop table: sales(id, shop_id, user_id, device_id, customer_id, customer_name,
5
+ * customer_phone, subtotal, discount_amount, tax_amount, total_amount, paid_amount,
6
+ * payment_method, type, status, note, created_at, updated_at)
7
+ *
8
+ * Desktop sale_items table: sale_items(id, sale_id, product_id, variation_name,
9
+ * product_name, quantity, unit_price, discount, total_price, created_at)
10
+ *
11
+ * Types match @soostori/sales canonical shapes exactly.
12
+ */
13
+ import type { SaleId, ShopId, UserId, DeviceId, CustomerId, ISO8601, Money, UUID } from '@soostori/core';
14
+ export type SaleType = 'retail' | 'wholesale';
15
+ export type SaleStatus = 'pending' | 'confirmed' | 'rejected' | 'completed' | 'refunded' | 'cancelled';
16
+ export type PaymentMethod = 'cash' | 'mobile_money' | 'card' | 'transfer' | 'debt';
17
+ export interface Sale {
18
+ id: SaleId;
19
+ shopId: ShopId;
20
+ userId: UserId;
21
+ deviceId: DeviceId;
22
+ type: SaleType;
23
+ status: SaleStatus;
24
+ authorizedBy: UUID | null;
25
+ subtotal: Money;
26
+ discountAmount: Money;
27
+ taxAmount: Money;
28
+ totalAmount: Money;
29
+ paidAmount: Money;
30
+ paymentMethod: PaymentMethod;
31
+ note: string | null;
32
+ customerId: CustomerId | null;
33
+ customerName: string | null;
34
+ customerIdNumber: string | null;
35
+ itemsSummary: string | null;
36
+ createdAt: ISO8601;
37
+ updatedAt: ISO8601;
38
+ confirmedAt: ISO8601 | null;
39
+ }
40
+ export interface SaleItem {
41
+ id: SaleId;
42
+ saleId: SaleId;
43
+ productId: UUID | null;
44
+ productName: string;
45
+ variationName: string | null;
46
+ quantity: number;
47
+ unitPrice: Money;
48
+ discount: Money;
49
+ totalPrice: Money;
50
+ }
51
+ export interface HeldSale {
52
+ id: UUID;
53
+ shopId: ShopId;
54
+ name: string | null;
55
+ cartItems: string;
56
+ paymentMethod: PaymentMethod;
57
+ createdAt: ISO8601;
58
+ userId: UserId;
59
+ }
60
+ export declare class DesktopSalesRepository {
61
+ private tableName;
62
+ findById(id: SaleId): Promise<Sale | null>;
63
+ findMany(filter?: {
64
+ status?: Sale['status'];
65
+ startDate?: ISO8601;
66
+ endDate?: ISO8601;
67
+ customerId?: string;
68
+ userId?: string;
69
+ deviceId?: string;
70
+ paymentMethod?: Sale['paymentMethod'];
71
+ }): Promise<Sale[]>;
72
+ create(sale: Sale, items: SaleItem[]): Promise<Sale>;
73
+ update(id: SaleId, changes: Partial<Sale>): Promise<Sale>;
74
+ findItemsBySaleId(saleId: SaleId): Promise<SaleItem[]>;
75
+ findHeldSales(_shopId: ShopId): Promise<HeldSale[]>;
76
+ createHeldSale(data: {
77
+ id: UUID;
78
+ shopId: ShopId;
79
+ name: string | null;
80
+ cartItems: string;
81
+ paymentMethod: PaymentMethod;
82
+ userId: UserId;
83
+ }): Promise<HeldSale>;
84
+ deleteHeldSale(id: UUID): Promise<void>;
85
+ totals(_filter?: {
86
+ status?: Sale['status'];
87
+ startDate?: ISO8601;
88
+ endDate?: ISO8601;
89
+ }): Promise<{
90
+ count: number;
91
+ total: Money;
92
+ byPaymentMethod: Record<string, Money>;
93
+ }>;
94
+ }
95
+ //# sourceMappingURL=sales-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sales-repository.d.ts","sourceRoot":"","sources":["../src/sales-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAKxG,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAA;AAC7C,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,CAAA;AACtG,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAA;AAElF,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,QAAQ,CAAA;IAClB,IAAI,EAAE,QAAQ,CAAA;IACd,MAAM,EAAE,UAAU,CAAA;IAClB,YAAY,EAAE,IAAI,GAAG,IAAI,CAAA;IACzB,QAAQ,EAAE,KAAK,CAAA;IACf,cAAc,EAAE,KAAK,CAAA;IACrB,SAAS,EAAE,KAAK,CAAA;IAChB,WAAW,EAAE,KAAK,CAAA;IAClB,UAAU,EAAE,KAAK,CAAA;IACjB,aAAa,EAAE,aAAa,CAAA;IAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAA;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,IAAI,GAAG,IAAI,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,KAAK,CAAA;IAChB,QAAQ,EAAE,KAAK,CAAA;IACf,UAAU,EAAE,KAAK,CAAA;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,IAAI,CAAA;IACR,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,aAAa,CAAA;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACf;AAkDD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,SAAS,CAAU;IAErB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAO1C,QAAQ,CAAC,MAAM,CAAC,EAAE;QACtB,MAAM,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,aAAa,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAA;KACtC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAgBb,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDpD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzD,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAiBtD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAkBnD,cAAc,CAAC,IAAI,EAAE;QACzB,EAAE,EAAE,IAAI,CAAA;QACR,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,SAAS,EAAE,MAAM,CAAA;QACjB,aAAa,EAAE,aAAa,CAAA;QAC5B,MAAM,EAAE,MAAM,CAAA;KACf,GAAG,OAAO,CAAC,QAAQ,CAAC;IAUf,cAAc,CAAC,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,MAAM,CAAC,OAAO,CAAC,EAAE;QACrB,MAAM,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;KAAE,CAAC;CAGrF"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Sales repository — implements SalesRepository contract over Desktop sales table.
3
+ *
4
+ * Desktop table: sales(id, shop_id, user_id, device_id, customer_id, customer_name,
5
+ * customer_phone, subtotal, discount_amount, tax_amount, total_amount, paid_amount,
6
+ * payment_method, type, status, note, created_at, updated_at)
7
+ *
8
+ * Desktop sale_items table: sale_items(id, sale_id, product_id, variation_name,
9
+ * product_name, quantity, unit_price, discount, total_price, created_at)
10
+ *
11
+ * Types match @soostori/sales canonical shapes exactly.
12
+ */
13
+ import { getDatabase } from './sqlite-database.js';
14
+ import { asSaleId, asShopId } from '@soostori/core';
15
+ // ── Row mappers ──────────────────────────────────────────────────────────
16
+ function rowToSale(row) {
17
+ return {
18
+ id: asSaleId(row.id),
19
+ shopId: asShopId(row.shop_id),
20
+ userId: row.user_id,
21
+ deviceId: row.device_id,
22
+ type: row.type,
23
+ status: row.status,
24
+ authorizedBy: null,
25
+ subtotal: row.subtotal,
26
+ discountAmount: row.discount_amount,
27
+ taxAmount: row.tax_amount,
28
+ totalAmount: row.total_amount,
29
+ paidAmount: row.paid_amount,
30
+ paymentMethod: row.payment_method,
31
+ note: row.note ?? null,
32
+ customerId: (row.customer_id ?? null),
33
+ customerName: row.customer_name ?? null,
34
+ customerIdNumber: row.customer_phone ?? null,
35
+ itemsSummary: null,
36
+ createdAt: row.created_at,
37
+ updatedAt: row.updated_at,
38
+ confirmedAt: null,
39
+ };
40
+ }
41
+ // ── Repository implementation ───────────────────────────────────────────────
42
+ export class DesktopSalesRepository {
43
+ tableName = 'sales';
44
+ async findById(id) {
45
+ const row = getDatabase()
46
+ .prepare(`SELECT * FROM ${this.tableName} WHERE id = ?`)
47
+ .get(id);
48
+ return row ? rowToSale(row) : null;
49
+ }
50
+ async findMany(filter) {
51
+ const db = getDatabase();
52
+ const conditions = [];
53
+ const values = [];
54
+ if (filter?.status) {
55
+ conditions.push('status = ?');
56
+ values.push(filter.status);
57
+ }
58
+ if (filter?.userId) {
59
+ conditions.push('user_id = ?');
60
+ values.push(filter.userId);
61
+ }
62
+ if (filter?.deviceId) {
63
+ conditions.push('device_id = ?');
64
+ values.push(filter.deviceId);
65
+ }
66
+ if (filter?.paymentMethod) {
67
+ conditions.push('payment_method = ?');
68
+ values.push(filter.paymentMethod);
69
+ }
70
+ if (filter?.startDate) {
71
+ conditions.push('created_at >= ?');
72
+ values.push(filter.startDate);
73
+ }
74
+ if (filter?.endDate) {
75
+ conditions.push('created_at <= ?');
76
+ values.push(filter.endDate);
77
+ }
78
+ const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
79
+ const rows = db.prepare(`SELECT * FROM ${this.tableName} ${where} ORDER BY created_at DESC`)
80
+ .all(...values);
81
+ return rows.map(rowToSale);
82
+ }
83
+ async create(sale, items) {
84
+ // Idempotent: if this saleId already exists, return it without re-inserting.
85
+ const existing = await this.findById(sale.id);
86
+ if (existing)
87
+ return existing;
88
+ const db = getDatabase();
89
+ const now = new Date().toISOString();
90
+ db.prepare(`
91
+ INSERT INTO sales (id, shop_id, user_id, device_id, customer_id, customer_name, customer_phone,
92
+ subtotal, discount_amount, tax_amount, total_amount, paid_amount, payment_method, type, status,
93
+ note, created_at, updated_at)
94
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
95
+ `).run(sale.id, sale.shopId, sale.userId, sale.deviceId, sale.customerId, sale.customerName, null, sale.subtotal, sale.discountAmount, sale.taxAmount, sale.totalAmount, sale.paidAmount, sale.paymentMethod, sale.type, sale.status, sale.note, sale.createdAt ?? now, sale.updatedAt ?? now);
96
+ const insertItem = db.prepare(`
97
+ INSERT INTO sale_items (id, sale_id, product_id, variation_name, product_name, quantity, unit_price, discount, total_price, shop_id, created_at)
98
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
99
+ `);
100
+ for (const item of items) {
101
+ insertItem.run(item.id, sale.id, item.productId, item.variationName, item.productName, item.quantity, item.unitPrice, item.discount, item.totalPrice, sale.shopId, now);
102
+ }
103
+ return sale;
104
+ }
105
+ async update(id, changes) {
106
+ const db = getDatabase();
107
+ const fields = Object.keys(changes);
108
+ const vals = fields.map(k => changes[k]);
109
+ const setClause = fields.map(f => `${f} = ?`).join(', ');
110
+ db.prepare(`UPDATE ${this.tableName} SET ${setClause}, updated_at = ? WHERE id = ?`)
111
+ .run(...vals, new Date().toISOString(), id);
112
+ return (await this.findById(id));
113
+ }
114
+ async findItemsBySaleId(saleId) {
115
+ const rows = getDatabase()
116
+ .prepare('SELECT * FROM sale_items WHERE sale_id = ?')
117
+ .all(saleId);
118
+ return rows.map(r => ({
119
+ id: asSaleId(r.id),
120
+ saleId: asSaleId(r.sale_id),
121
+ productId: (r.product_id ?? null),
122
+ productName: r.product_name,
123
+ variationName: r.variation_name ?? null,
124
+ quantity: r.quantity,
125
+ unitPrice: r.unit_price,
126
+ discount: r.discount,
127
+ totalPrice: r.total_price,
128
+ }));
129
+ }
130
+ async findHeldSales(_shopId) {
131
+ const rows = getDatabase()
132
+ .prepare('SELECT * FROM held_sales ORDER BY created_at DESC')
133
+ .all();
134
+ return rows.map(r => ({
135
+ id: r.id,
136
+ shopId: r.shop_id,
137
+ name: r.name,
138
+ cartItems: r.cart_items,
139
+ paymentMethod: r.payment_method,
140
+ createdAt: r.created_at,
141
+ userId: r.user_id,
142
+ }));
143
+ }
144
+ async createHeldSale(data) {
145
+ const db = getDatabase();
146
+ const now = new Date().toISOString();
147
+ db.prepare(`
148
+ INSERT INTO held_sales (id, shop_id, name, cart_items, payment_method, user_id, created_at)
149
+ VALUES (?, ?, ?, ?, ?, ?, ?)
150
+ `).run(data.id, data.shopId, data.name ?? null, data.cartItems, data.paymentMethod, data.userId, now);
151
+ return { ...data, createdAt: now };
152
+ }
153
+ async deleteHeldSale(id) {
154
+ getDatabase().prepare('DELETE FROM held_sales WHERE id = ?').run(id);
155
+ }
156
+ async totals(_filter) {
157
+ return { count: 0, total: 0, byPaymentMethod: {} };
158
+ }
159
+ }
160
+ //# sourceMappingURL=sales-repository.js.map